--
-- PostgreSQL database dump
--

-- Dumped from database version 15.8
-- Dumped by pg_dump version 15.8

SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;

--
-- Name: _realtime; Type: SCHEMA; Schema: -; Owner: postgres
--

CREATE SCHEMA _realtime;


ALTER SCHEMA _realtime OWNER TO postgres;

--
-- Name: auth; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA auth;


ALTER SCHEMA auth OWNER TO supabase_admin;

--
-- Name: pg_cron; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS pg_cron WITH SCHEMA pg_catalog;


--
-- Name: EXTENSION pg_cron; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION pg_cron IS 'Job scheduler for PostgreSQL';


--
-- Name: extensions; Type: SCHEMA; Schema: -; Owner: postgres
--

CREATE SCHEMA extensions;


ALTER SCHEMA extensions OWNER TO postgres;

--
-- Name: graphql; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA graphql;


ALTER SCHEMA graphql OWNER TO supabase_admin;

--
-- Name: graphql_public; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA graphql_public;


ALTER SCHEMA graphql_public OWNER TO supabase_admin;

--
-- Name: pg_net; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS pg_net WITH SCHEMA extensions;


--
-- Name: EXTENSION pg_net; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION pg_net IS 'Async HTTP';


--
-- Name: pgbouncer; Type: SCHEMA; Schema: -; Owner: pgbouncer
--

CREATE SCHEMA pgbouncer;


ALTER SCHEMA pgbouncer OWNER TO pgbouncer;

--
-- Name: pgsodium; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA pgsodium;


ALTER SCHEMA pgsodium OWNER TO supabase_admin;

--
-- Name: pgsodium; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS pgsodium WITH SCHEMA pgsodium;


--
-- Name: EXTENSION pgsodium; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION pgsodium IS 'Pgsodium is a modern cryptography library for Postgres.';


--
-- Name: realtime; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA realtime;


ALTER SCHEMA realtime OWNER TO supabase_admin;

--
-- Name: storage; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA storage;


ALTER SCHEMA storage OWNER TO supabase_admin;

--
-- Name: supabase_functions; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA supabase_functions;


ALTER SCHEMA supabase_functions OWNER TO supabase_admin;

--
-- Name: supabase_migrations; Type: SCHEMA; Schema: -; Owner: postgres
--

CREATE SCHEMA supabase_migrations;


ALTER SCHEMA supabase_migrations OWNER TO postgres;

--
-- Name: vault; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA vault;


ALTER SCHEMA vault OWNER TO supabase_admin;

--
-- Name: pg_graphql; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS pg_graphql WITH SCHEMA graphql;


--
-- Name: EXTENSION pg_graphql; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION pg_graphql IS 'pg_graphql: GraphQL support';


--
-- Name: pg_stat_statements; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS pg_stat_statements WITH SCHEMA extensions;


--
-- Name: EXTENSION pg_stat_statements; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION pg_stat_statements IS 'track planning and execution statistics of all SQL statements executed';


--
-- Name: pgcrypto; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA extensions;


--
-- Name: EXTENSION pgcrypto; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION pgcrypto IS 'cryptographic functions';


--
-- Name: pgjwt; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS pgjwt WITH SCHEMA extensions;


--
-- Name: EXTENSION pgjwt; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION pgjwt IS 'JSON Web Token API for Postgresql';


--
-- Name: supabase_vault; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS supabase_vault WITH SCHEMA vault;


--
-- Name: EXTENSION supabase_vault; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION supabase_vault IS 'Supabase Vault Extension';


--
-- Name: uuid-ossp; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA extensions;


--
-- Name: EXTENSION "uuid-ossp"; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION "uuid-ossp" IS 'generate universally unique identifiers (UUIDs)';


--
-- Name: aal_level; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.aal_level AS ENUM (
    'aal1',
    'aal2',
    'aal3'
);


ALTER TYPE auth.aal_level OWNER TO supabase_auth_admin;

--
-- Name: code_challenge_method; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.code_challenge_method AS ENUM (
    's256',
    'plain'
);


ALTER TYPE auth.code_challenge_method OWNER TO supabase_auth_admin;

--
-- Name: factor_status; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.factor_status AS ENUM (
    'unverified',
    'verified'
);


ALTER TYPE auth.factor_status OWNER TO supabase_auth_admin;

--
-- Name: factor_type; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.factor_type AS ENUM (
    'totp',
    'webauthn',
    'phone'
);


ALTER TYPE auth.factor_type OWNER TO supabase_auth_admin;

--
-- Name: one_time_token_type; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.one_time_token_type AS ENUM (
    'confirmation_token',
    'reauthentication_token',
    'recovery_token',
    'email_change_token_new',
    'email_change_token_current',
    'phone_change_token'
);


ALTER TYPE auth.one_time_token_type OWNER TO supabase_auth_admin;

--
-- Name: class_type; Type: TYPE; Schema: public; Owner: postgres
--

CREATE TYPE public.class_type AS ENUM (
    'morning',
    'evening',
    'private'
);


ALTER TYPE public.class_type OWNER TO postgres;

--
-- Name: membership_type; Type: TYPE; Schema: public; Owner: postgres
--

CREATE TYPE public.membership_type AS ENUM (
    'single_class',
    'two_classes',
    'ten_classes',
    'single_monthly',
    'double_monthly'
);


ALTER TYPE public.membership_type OWNER TO postgres;

--
-- Name: action; Type: TYPE; Schema: realtime; Owner: supabase_admin
--

CREATE TYPE realtime.action AS ENUM (
    'INSERT',
    'UPDATE',
    'DELETE',
    'TRUNCATE',
    'ERROR'
);


ALTER TYPE realtime.action OWNER TO supabase_admin;

--
-- Name: equality_op; Type: TYPE; Schema: realtime; Owner: supabase_admin
--

CREATE TYPE realtime.equality_op AS ENUM (
    'eq',
    'neq',
    'lt',
    'lte',
    'gt',
    'gte',
    'in'
);


ALTER TYPE realtime.equality_op OWNER TO supabase_admin;

--
-- Name: user_defined_filter; Type: TYPE; Schema: realtime; Owner: supabase_admin
--

CREATE TYPE realtime.user_defined_filter AS (
	column_name text,
	op realtime.equality_op,
	value text
);


ALTER TYPE realtime.user_defined_filter OWNER TO supabase_admin;

--
-- Name: wal_column; Type: TYPE; Schema: realtime; Owner: supabase_admin
--

CREATE TYPE realtime.wal_column AS (
	name text,
	type_name text,
	type_oid oid,
	value jsonb,
	is_pkey boolean,
	is_selectable boolean
);


ALTER TYPE realtime.wal_column OWNER TO supabase_admin;

--
-- Name: wal_rls; Type: TYPE; Schema: realtime; Owner: supabase_admin
--

CREATE TYPE realtime.wal_rls AS (
	wal jsonb,
	is_rls_enabled boolean,
	subscription_ids uuid[],
	errors text[]
);


ALTER TYPE realtime.wal_rls OWNER TO supabase_admin;

--
-- Name: email(); Type: FUNCTION; Schema: auth; Owner: supabase_auth_admin
--

CREATE FUNCTION auth.email() RETURNS text
    LANGUAGE sql STABLE
    AS $$
  select 
  coalesce(
    nullif(current_setting('request.jwt.claim.email', true), ''),
    (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'email')
  )::text
$$;


ALTER FUNCTION auth.email() OWNER TO supabase_auth_admin;

--
-- Name: FUNCTION email(); Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON FUNCTION auth.email() IS 'Deprecated. Use auth.jwt() -> ''email'' instead.';


--
-- Name: jwt(); Type: FUNCTION; Schema: auth; Owner: supabase_auth_admin
--

CREATE FUNCTION auth.jwt() RETURNS jsonb
    LANGUAGE sql STABLE
    AS $$
  select 
    coalesce(
        nullif(current_setting('request.jwt.claim', true), ''),
        nullif(current_setting('request.jwt.claims', true), '')
    )::jsonb
$$;


ALTER FUNCTION auth.jwt() OWNER TO supabase_auth_admin;

--
-- Name: role(); Type: FUNCTION; Schema: auth; Owner: supabase_auth_admin
--

CREATE FUNCTION auth.role() RETURNS text
    LANGUAGE sql STABLE
    AS $$
  select 
  coalesce(
    nullif(current_setting('request.jwt.claim.role', true), ''),
    (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'role')
  )::text
$$;


ALTER FUNCTION auth.role() OWNER TO supabase_auth_admin;

--
-- Name: FUNCTION role(); Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON FUNCTION auth.role() IS 'Deprecated. Use auth.jwt() -> ''role'' instead.';


--
-- Name: uid(); Type: FUNCTION; Schema: auth; Owner: supabase_auth_admin
--

CREATE FUNCTION auth.uid() RETURNS uuid
    LANGUAGE sql STABLE
    AS $$
  select 
  coalesce(
    nullif(current_setting('request.jwt.claim.sub', true), ''),
    (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'sub')
  )::uuid
$$;


ALTER FUNCTION auth.uid() OWNER TO supabase_auth_admin;

--
-- Name: FUNCTION uid(); Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON FUNCTION auth.uid() IS 'Deprecated. Use auth.jwt() -> ''sub'' instead.';


--
-- Name: grant_pg_cron_access(); Type: FUNCTION; Schema: extensions; Owner: postgres
--

CREATE FUNCTION extensions.grant_pg_cron_access() RETURNS event_trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  IF EXISTS (
    SELECT
    FROM pg_event_trigger_ddl_commands() AS ev
    JOIN pg_extension AS ext
    ON ev.objid = ext.oid
    WHERE ext.extname = 'pg_cron'
  )
  THEN
    grant usage on schema cron to postgres with grant option;

    alter default privileges in schema cron grant all on tables to postgres with grant option;
    alter default privileges in schema cron grant all on functions to postgres with grant option;
    alter default privileges in schema cron grant all on sequences to postgres with grant option;

    alter default privileges for user supabase_admin in schema cron grant all
        on sequences to postgres with grant option;
    alter default privileges for user supabase_admin in schema cron grant all
        on tables to postgres with grant option;
    alter default privileges for user supabase_admin in schema cron grant all
        on functions to postgres with grant option;

    grant all privileges on all tables in schema cron to postgres with grant option;
    revoke all on table cron.job from postgres;
    grant select on table cron.job to postgres with grant option;
  END IF;
END;
$$;


ALTER FUNCTION extensions.grant_pg_cron_access() OWNER TO postgres;

--
-- Name: FUNCTION grant_pg_cron_access(); Type: COMMENT; Schema: extensions; Owner: postgres
--

COMMENT ON FUNCTION extensions.grant_pg_cron_access() IS 'Grants access to pg_cron';


--
-- Name: grant_pg_graphql_access(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin
--

CREATE FUNCTION extensions.grant_pg_graphql_access() RETURNS event_trigger
    LANGUAGE plpgsql
    AS $_$
DECLARE
    func_is_graphql_resolve bool;
BEGIN
    func_is_graphql_resolve = (
        SELECT n.proname = 'resolve'
        FROM pg_event_trigger_ddl_commands() AS ev
        LEFT JOIN pg_catalog.pg_proc AS n
        ON ev.objid = n.oid
    );

    IF func_is_graphql_resolve
    THEN
        -- Update public wrapper to pass all arguments through to the pg_graphql resolve func
        DROP FUNCTION IF EXISTS graphql_public.graphql;
        create or replace function graphql_public.graphql(
            "operationName" text default null,
            query text default null,
            variables jsonb default null,
            extensions jsonb default null
        )
            returns jsonb
            language sql
        as $$
            select graphql.resolve(
                query := query,
                variables := coalesce(variables, '{}'),
                "operationName" := "operationName",
                extensions := extensions
            );
        $$;

        -- This hook executes when `graphql.resolve` is created. That is not necessarily the last
        -- function in the extension so we need to grant permissions on existing entities AND
        -- update default permissions to any others that are created after `graphql.resolve`
        grant usage on schema graphql to postgres, anon, authenticated, service_role;
        grant select on all tables in schema graphql to postgres, anon, authenticated, service_role;
        grant execute on all functions in schema graphql to postgres, anon, authenticated, service_role;
        grant all on all sequences in schema graphql to postgres, anon, authenticated, service_role;
        alter default privileges in schema graphql grant all on tables to postgres, anon, authenticated, service_role;
        alter default privileges in schema graphql grant all on functions to postgres, anon, authenticated, service_role;
        alter default privileges in schema graphql grant all on sequences to postgres, anon, authenticated, service_role;

        -- Allow postgres role to allow granting usage on graphql and graphql_public schemas to custom roles
        grant usage on schema graphql_public to postgres with grant option;
        grant usage on schema graphql to postgres with grant option;
    END IF;

END;
$_$;


ALTER FUNCTION extensions.grant_pg_graphql_access() OWNER TO supabase_admin;

--
-- Name: FUNCTION grant_pg_graphql_access(); Type: COMMENT; Schema: extensions; Owner: supabase_admin
--

COMMENT ON FUNCTION extensions.grant_pg_graphql_access() IS 'Grants access to pg_graphql';


--
-- Name: grant_pg_net_access(); Type: FUNCTION; Schema: extensions; Owner: postgres
--

CREATE FUNCTION extensions.grant_pg_net_access() RETURNS event_trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  IF EXISTS (
    SELECT 1
    FROM pg_event_trigger_ddl_commands() AS ev
    JOIN pg_extension AS ext
    ON ev.objid = ext.oid
    WHERE ext.extname = 'pg_net'
  )
  THEN
    GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role;

    ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
    ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;

    ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
    ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;

    REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
    REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;

    GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
    GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
  END IF;
END;
$$;


ALTER FUNCTION extensions.grant_pg_net_access() OWNER TO postgres;

--
-- Name: FUNCTION grant_pg_net_access(); Type: COMMENT; Schema: extensions; Owner: postgres
--

COMMENT ON FUNCTION extensions.grant_pg_net_access() IS 'Grants access to pg_net';


--
-- Name: pgrst_ddl_watch(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin
--

CREATE FUNCTION extensions.pgrst_ddl_watch() RETURNS event_trigger
    LANGUAGE plpgsql
    AS $$
DECLARE
  cmd record;
BEGIN
  FOR cmd IN SELECT * FROM pg_event_trigger_ddl_commands()
  LOOP
    IF cmd.command_tag IN (
      'CREATE SCHEMA', 'ALTER SCHEMA'
    , 'CREATE TABLE', 'CREATE TABLE AS', 'SELECT INTO', 'ALTER TABLE'
    , 'CREATE FOREIGN TABLE', 'ALTER FOREIGN TABLE'
    , 'CREATE VIEW', 'ALTER VIEW'
    , 'CREATE MATERIALIZED VIEW', 'ALTER MATERIALIZED VIEW'
    , 'CREATE FUNCTION', 'ALTER FUNCTION'
    , 'CREATE TRIGGER'
    , 'CREATE TYPE', 'ALTER TYPE'
    , 'CREATE RULE'
    , 'COMMENT'
    )
    -- don't notify in case of CREATE TEMP table or other objects created on pg_temp
    AND cmd.schema_name is distinct from 'pg_temp'
    THEN
      NOTIFY pgrst, 'reload schema';
    END IF;
  END LOOP;
END; $$;


ALTER FUNCTION extensions.pgrst_ddl_watch() OWNER TO supabase_admin;

--
-- Name: pgrst_drop_watch(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin
--

CREATE FUNCTION extensions.pgrst_drop_watch() RETURNS event_trigger
    LANGUAGE plpgsql
    AS $$
DECLARE
  obj record;
BEGIN
  FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
  LOOP
    IF obj.object_type IN (
      'schema'
    , 'table'
    , 'foreign table'
    , 'view'
    , 'materialized view'
    , 'function'
    , 'trigger'
    , 'type'
    , 'rule'
    )
    AND obj.is_temporary IS false -- no pg_temp objects
    THEN
      NOTIFY pgrst, 'reload schema';
    END IF;
  END LOOP;
END; $$;


ALTER FUNCTION extensions.pgrst_drop_watch() OWNER TO supabase_admin;

--
-- Name: set_graphql_placeholder(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin
--

CREATE FUNCTION extensions.set_graphql_placeholder() RETURNS event_trigger
    LANGUAGE plpgsql
    AS $_$
    DECLARE
    graphql_is_dropped bool;
    BEGIN
    graphql_is_dropped = (
        SELECT ev.schema_name = 'graphql_public'
        FROM pg_event_trigger_dropped_objects() AS ev
        WHERE ev.schema_name = 'graphql_public'
    );

    IF graphql_is_dropped
    THEN
        create or replace function graphql_public.graphql(
            "operationName" text default null,
            query text default null,
            variables jsonb default null,
            extensions jsonb default null
        )
            returns jsonb
            language plpgsql
        as $$
            DECLARE
                server_version float;
            BEGIN
                server_version = (SELECT (SPLIT_PART((select version()), ' ', 2))::float);

                IF server_version >= 14 THEN
                    RETURN jsonb_build_object(
                        'errors', jsonb_build_array(
                            jsonb_build_object(
                                'message', 'pg_graphql extension is not enabled.'
                            )
                        )
                    );
                ELSE
                    RETURN jsonb_build_object(
                        'errors', jsonb_build_array(
                            jsonb_build_object(
                                'message', 'pg_graphql is only available on projects running Postgres 14 onwards.'
                            )
                        )
                    );
                END IF;
            END;
        $$;
    END IF;

    END;
$_$;


ALTER FUNCTION extensions.set_graphql_placeholder() OWNER TO supabase_admin;

--
-- Name: FUNCTION set_graphql_placeholder(); Type: COMMENT; Schema: extensions; Owner: supabase_admin
--

COMMENT ON FUNCTION extensions.set_graphql_placeholder() IS 'Reintroduces placeholder function for graphql_public.graphql';


--
-- Name: get_auth(text); Type: FUNCTION; Schema: pgbouncer; Owner: postgres
--

CREATE FUNCTION pgbouncer.get_auth(p_usename text) RETURNS TABLE(username text, password text)
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
BEGIN
    RAISE WARNING 'PgBouncer auth request: %', p_usename;

    RETURN QUERY
    SELECT usename::TEXT, passwd::TEXT FROM pg_catalog.pg_shadow
    WHERE usename = p_usename;
END;
$$;


ALTER FUNCTION pgbouncer.get_auth(p_usename text) OWNER TO postgres;

--
-- Name: check_card_member_match(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.check_card_member_match() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
DECLARE
  v_card_member_id UUID;
BEGIN
  -- 如果没有指定会员卡，则跳过验证
  IF NEW.card_id IS NULL THEN
    RETURN NEW;
  END IF;
  
  -- 获取会员卡所属的会员ID
  SELECT member_id INTO v_card_member_id
  FROM membership_cards
  WHERE id = NEW.card_id;
  
  -- 验证会员卡是否属于该会员
  IF v_card_member_id != NEW.member_id THEN
    RAISE EXCEPTION '会员卡不属于该会员
Membership card does not belong to this member';
  END IF;
  
  RETURN NEW;
END;
$$;


ALTER FUNCTION public.check_card_member_match() OWNER TO postgres;

--
-- Name: check_card_validity(uuid, uuid, text, date, uuid); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.check_card_validity(p_card_id uuid, p_member_id uuid, p_class_type text, p_check_in_date date, p_trainer_id uuid DEFAULT NULL::uuid) RETURNS jsonb
    LANGUAGE plpgsql
    AS $$
DECLARE
  v_card RECORD;
  v_class_type class_type;
  v_is_private boolean;
  v_result jsonb;
  v_trainer_type text;
BEGIN
  -- 记录开始验证
  PERFORM log_debug(
    'check_card_validity',
    '开始验证会员卡',
    jsonb_build_object(
      'card_id', p_card_id,
      'member_id', p_member_id,
      'class_type', p_class_type,
      'check_in_date', p_check_in_date,
      'trainer_id', p_trainer_id
    )
  );

  -- 转换课程类型
  BEGIN
    v_class_type := p_class_type::class_type;
    v_is_private := (v_class_type = 'private');
  EXCEPTION WHEN OTHERS THEN
    PERFORM log_debug(
      'check_card_validity',
      '无效的课程类型',
      jsonb_build_object(
        'class_type', p_class_type,
        'error', SQLERRM
      )
    );
    RETURN jsonb_build_object(
      'is_valid', false,
      'reason', '无效的课程类型',
      'details', jsonb_build_object(
        'class_type', p_class_type,
        'error', SQLERRM
      )
    );
  END;

  -- 获取会员卡信息
  SELECT *
  INTO v_card
  FROM membership_cards
  WHERE id = p_card_id
  FOR UPDATE;

  -- 检查会员卡是否存在
  IF NOT FOUND THEN
    PERFORM log_debug(
      'check_card_validity',
      '会员卡不存在',
      jsonb_build_object(
        'card_id', p_card_id
      )
    );
    RETURN jsonb_build_object(
      'is_valid', false,
      'reason', '会员卡不存在'
    );
  END IF;

  -- 检查会员卡是否属于该会员
  IF v_card.member_id != p_member_id THEN
    PERFORM log_debug(
      'check_card_validity',
      '会员卡不属于该会员',
      jsonb_build_object(
        'card_member_id', v_card.member_id,
        'requested_member_id', p_member_id
      )
    );
    RETURN jsonb_build_object(
      'is_valid', false,
      'reason', '会员卡不属于该会员'
    );
  END IF;

  -- 检查会员卡是否过期
  IF v_card.valid_until IS NOT NULL AND v_card.valid_until < p_check_in_date THEN
    PERFORM log_debug(
      'check_card_validity',
      '会员卡已过期',
      jsonb_build_object(
        'valid_until', v_card.valid_until,
        'check_in_date', p_check_in_date
      )
    );
    RETURN jsonb_build_object(
      'is_valid', false,
      'reason', '会员卡已过期',
      'details', jsonb_build_object(
        'valid_until', v_card.valid_until,
        'check_in_date', p_check_in_date
      )
    );
  END IF;

  -- 修复：检查卡类型是否匹配课程类型
  IF (v_card.card_type = '私教课' AND NOT v_is_private) OR
     (v_card.card_type = '团课' AND v_is_private) THEN
    PERFORM log_debug(
      'check_card_validity',
      '卡类型不匹配课程类型',
      jsonb_build_object(
        'card_type', v_card.card_type,
        'class_type', p_class_type,
        'is_private', v_is_private
      )
    );
    RETURN jsonb_build_object(
      'is_valid', false,
      'reason', '卡类型不匹配课程类型',
      'details', jsonb_build_object(
        'card_type', v_card.card_type,
        'class_type', p_class_type,
        'is_private', v_is_private
      )
    );
  END IF;

  -- 检查私教课时是否足够
  IF v_card.card_type = '私教课' AND
     (v_card.remaining_private_sessions IS NULL OR v_card.remaining_private_sessions <= 0) THEN
    PERFORM log_debug(
      'check_card_validity',
      '私教课时不足',
      jsonb_build_object(
        'remaining_private_sessions', v_card.remaining_private_sessions
      )
    );
    RETURN jsonb_build_object(
      'is_valid', false,
      'reason', '私教课时不足',
      'details', jsonb_build_object(
        'remaining_private_sessions', v_card.remaining_private_sessions
      )
    );
  END IF;

  -- 检查团课课时是否足够
  IF v_card.card_type = '团课' AND v_card.card_category = '课时卡' AND
     (v_card.remaining_group_sessions IS NULL OR v_card.remaining_group_sessions <= 0) THEN
    PERFORM log_debug(
      'check_card_validity',
      '团课课时不足',
      jsonb_build_object(
        'remaining_group_sessions', v_card.remaining_group_sessions
      )
    );
    RETURN jsonb_build_object(
      'is_valid', false,
      'reason', '团课课时不足',
      'details', jsonb_build_object(
        'remaining_group_sessions', v_card.remaining_group_sessions
      )
    );
  END IF;

  -- 会员卡有效
  RETURN jsonb_build_object(
    'is_valid', true,
    'card_info', jsonb_build_object(
      'card_id', v_card.id,
      'card_type', v_card.card_type,
      'card_category', v_card.card_category,
      'card_subtype', v_card.card_subtype,
      'valid_until', v_card.valid_until,
      'remaining_group_sessions', v_card.remaining_group_sessions,
      'remaining_private_sessions', v_card.remaining_private_sessions
    )
  );
END;
$$;


ALTER FUNCTION public.check_card_validity(p_card_id uuid, p_member_id uuid, p_class_type text, p_check_in_date date, p_trainer_id uuid) OWNER TO postgres;

--
-- Name: check_card_validity_detailed(uuid, uuid, text, date); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.check_card_validity_detailed(p_card_id uuid, p_member_id uuid, p_class_type text, p_check_in_date date) RETURNS jsonb
    LANGUAGE plpgsql
    AS $$
DECLARE
  v_card RECORD;
BEGIN
  -- 获取会员卡信息
  SELECT * INTO v_card FROM membership_cards WHERE id = p_card_id;
  
  -- 检查会员卡是否存在
  IF NOT FOUND THEN
    RETURN jsonb_build_object(
      'is_valid', FALSE,
      'reason', '会员卡不存在',
      'details', jsonb_build_object('card_id', p_card_id)
    );
  END IF;
  
  -- 检查会员卡是否属于该会员
  IF v_card.member_id != p_member_id THEN
    RETURN jsonb_build_object(
      'is_valid', FALSE,
      'reason', '会员卡不属于该会员',
      'details', jsonb_build_object(
        'card_member_id', v_card.member_id,
        'requested_member_id', p_member_id
      )
    );
  END IF;
  
  -- 检查会员卡是否过期
  IF v_card.valid_until IS NOT NULL AND v_card.valid_until < p_check_in_date THEN
    RETURN jsonb_build_object(
      'is_valid', FALSE,
      'reason', '会员卡已过期',
      'details', jsonb_build_object(
        'valid_until', v_card.valid_until,
        'check_in_date', p_check_in_date
      )
    );
  END IF;
  
  -- 检查卡类型是否匹配课程类型
  IF (v_card.card_type = '团课' AND p_class_type = 'private') OR 
     (v_card.card_type = '私教课' AND p_class_type != 'private') THEN
    RETURN jsonb_build_object(
      'is_valid', FALSE,
      'reason', '卡类型不匹配课程类型',
      'details', jsonb_build_object(
        'card_type', v_card.card_type,
        'class_type', p_class_type
      )
    );
  END IF;
  
  -- 检查团课课时卡课时是否足够
  IF v_card.card_type = '团课' AND v_card.card_category = '课时卡' AND
     (v_card.remaining_group_sessions IS NULL OR v_card.remaining_group_sessions <= 0) THEN
    RETURN jsonb_build_object(
      'is_valid', FALSE,
      'reason', '团课课时不足',
      'details', jsonb_build_object(
        'remaining_group_sessions', v_card.remaining_group_sessions
      )
    );
  END IF;
  
  -- 检查私教课时是否足够
  IF v_card.card_type = '私教课' AND
     (v_card.remaining_private_sessions IS NULL OR v_card.remaining_private_sessions <= 0) THEN
    RETURN jsonb_build_object(
      'is_valid', FALSE,
      'reason', '私教课时不足',
      'details', jsonb_build_object(
        'remaining_private_sessions', v_card.remaining_private_sessions
      )
    );
  END IF;
  
  -- 会员卡有效
  RETURN jsonb_build_object(
    'is_valid', TRUE,
    'card_info', jsonb_build_object(
      'card_id', v_card.id,
      'card_type', v_card.card_type,
      'card_category', v_card.card_category,
      'card_subtype', v_card.card_subtype,
      'valid_until', v_card.valid_until,
      'remaining_group_sessions', v_card.remaining_group_sessions,
      'remaining_private_sessions', v_card.remaining_private_sessions
    )
  );
END;
$$;


ALTER FUNCTION public.check_card_validity_detailed(p_card_id uuid, p_member_id uuid, p_class_type text, p_check_in_date date) OWNER TO postgres;

--
-- Name: check_duplicate_check_in(uuid, date, text, text); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.check_duplicate_check_in(p_member_id uuid, p_date date, p_class_type text, p_time_slot text DEFAULT NULL::text) RETURNS boolean
    LANGUAGE plpgsql
    AS $$ DECLARE v_class_type class_type; v_is_private boolean; v_duplicate_check_in RECORD; BEGIN PERFORM log_debug('check_duplicate_check_in', '开始检查重复签到', jsonb_build_object('member_id', p_member_id, 'date', p_date, 'class_type', p_class_type, 'time_slot', p_time_slot)); BEGIN v_class_type := p_class_type::class_type; v_is_private := (v_class_type = 'private'); EXCEPTION WHEN OTHERS THEN PERFORM log_debug('check_duplicate_check_in', '无效的课程类型', jsonb_build_object('class_type', p_class_type, 'error', SQLERRM)); RETURN false; END; SELECT * INTO v_duplicate_check_in FROM check_ins WHERE member_id = p_member_id AND check_in_date = p_date AND class_type = v_class_type AND (p_time_slot IS NULL OR time_slot = p_time_slot); IF FOUND THEN PERFORM log_debug('check_duplicate_check_in', '发现重复签到', jsonb_build_object('member_id', p_member_id, 'date', p_date, 'class_type', v_class_type, 'time_slot', COALESCE(p_time_slot, v_duplicate_check_in.time_slot), 'duplicate_check_in', jsonb_build_object('id', v_duplicate_check_in.id, 'check_in_date', v_duplicate_check_in.check_in_date, 'time_slot', v_duplicate_check_in.time_slot, 'is_extra', v_duplicate_check_in.is_extra))); RETURN true; END IF; PERFORM log_debug('check_duplicate_check_in', '未发现重复签到', jsonb_build_object('member_id', p_member_id, 'date', p_date, 'class_type', v_class_type, 'time_slot', p_time_slot)); RETURN false; END; $$;


ALTER FUNCTION public.check_duplicate_check_in(p_member_id uuid, p_date date, p_class_type text, p_time_slot text) OWNER TO postgres;

--
-- Name: check_duplicate_check_in_bool(uuid, date, text, text); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.check_duplicate_check_in_bool(p_member_id uuid, p_date date, p_class_type text, p_time_slot text DEFAULT NULL::text) RETURNS boolean
    LANGUAGE plpgsql
    AS $$
DECLARE
  v_result jsonb;
BEGIN
  v_result := check_duplicate_check_in(p_member_id, p_date, p_class_type, p_time_slot);
  RETURN (v_result->>'has_duplicate')::boolean;
END;
$$;


ALTER FUNCTION public.check_duplicate_check_in_bool(p_member_id uuid, p_date date, p_class_type text, p_time_slot text) OWNER TO postgres;

--
-- Name: check_duplicate_membership_cards(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.check_duplicate_membership_cards() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
    -- 检查是否已存在相同会员、相同卡类型和子类型的卡
    IF EXISTS (
        SELECT 1 FROM membership_cards 
        WHERE member_id = NEW.member_id 
        AND card_type = NEW.card_type 
        AND card_subtype = NEW.card_subtype
        AND id != NEW.id
    ) THEN
        RAISE EXCEPTION '会员已有相同类型和子类型的卡，请更新现有卡或选择不同的卡类型';
    END IF;
    RETURN NEW;
END;
$$;


ALTER FUNCTION public.check_duplicate_membership_cards() OWNER TO postgres;

--
-- Name: FUNCTION check_duplicate_membership_cards(); Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON FUNCTION public.check_duplicate_membership_cards() IS '检查并防止插入或更新重复的会员卡';


--
-- Name: check_in_logging(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.check_in_logging() RETURNS trigger
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
DECLARE
  v_member RECORD;
  v_card RECORD;
  v_trainer RECORD;
BEGIN
  -- Get member info
  SELECT name, email INTO v_member
  FROM members
  WHERE id = NEW.member_id;

  -- Get card info if exists
  SELECT id, card_type, card_category, card_subtype
  INTO v_card
  FROM membership_cards
  WHERE id = NEW.card_id;

  -- Get trainer info if exists
  SELECT name, type INTO v_trainer
  FROM trainers
  WHERE id = NEW.trainer_id;

  -- Log check-in details
  INSERT INTO check_in_logs (
    check_in_id,
    details,
    created_at
  ) VALUES (
    NEW.id,
    jsonb_build_object(
      'member_name', v_member.name,
      'member_email', v_member.email,
      'check_in_date', NEW.check_in_date,
      'time_slot', NEW.time_slot,
      'is_extra', NEW.is_extra,
      'is_private', NEW.is_private,
      'is_1v2', NEW.is_1v2,
      'card_id', NEW.card_id,
      'card_info', CASE WHEN v_card.id IS NOT NULL THEN 
        jsonb_build_object(
          'card_type', v_card.card_type,
          'card_category', v_card.card_category,
          'card_subtype', v_card.card_subtype
        )
      ELSE NULL END,
      'trainer_info', CASE WHEN v_trainer.name IS NOT NULL THEN
        jsonb_build_object(
          'name', v_trainer.name,
          'type', v_trainer.type
        )
      ELSE NULL END
    ),
    NOW()
  );

  RETURN NEW;
END;
$$;


ALTER FUNCTION public.check_in_logging() OWNER TO postgres;

--
-- Name: check_in_validation(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.check_in_validation() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
DECLARE
  v_duplicate_check_in RECORD;
  v_time_slot_valid boolean;
BEGIN
  -- 验证时间段格式
  IF NEW.time_slot IS NULL OR NEW.time_slot = '' THEN
    RAISE EXCEPTION '时间段不能为空
Time slot cannot be empty';
  END IF;

  -- 验证时间段有效性
  SELECT validate_time_slot(NEW.time_slot, NEW.check_in_date, NEW.is_private) INTO v_time_slot_valid;
  IF NOT v_time_slot_valid THEN
    RAISE EXCEPTION '无效的时间段: %
Invalid time slot: %', NEW.time_slot, NEW.time_slot;
  END IF;

  -- 设置课程类型
  IF NEW.is_private THEN
    NEW.class_type := 'private'::class_type;
  ELSE
    -- 根据时间段判断是上午还是下午课程
    IF NEW.time_slot = '09:00-10:30' THEN
      NEW.class_type := 'morning'::class_type;
    ELSE
      NEW.class_type := 'evening'::class_type;
    END IF;
  END IF;

  -- 检查是否有重复签到（修改：考虑课程类型）
  -- 原来的代码会检查相同会员、日期、时间段和是否私教，现在我们修改为检查相同会员、日期、时间段和相同课程类型
  SELECT * INTO v_duplicate_check_in
  FROM check_ins
  WHERE member_id = NEW.member_id
    AND check_in_date = NEW.check_in_date
    AND time_slot = NEW.time_slot
    AND class_type = NEW.class_type
    AND id IS DISTINCT FROM NEW.id
  LIMIT 1;

  IF FOUND THEN
    IF NEW.is_private THEN
      RAISE EXCEPTION '今天已经在这个时间段签到过私教课
Already checked in for private class at this time slot today';
    ELSE
      RAISE EXCEPTION '今天已经在这个时间段签到过团课
Already checked in for group class at this time slot today';
    END IF;
  END IF;

  RETURN NEW;
END;
$$;


ALTER FUNCTION public.check_in_validation() OWNER TO postgres;

--
-- Name: check_member_exists(uuid); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.check_member_exists(p_member_id uuid) RETURNS boolean
    LANGUAGE plpgsql
    AS $$
DECLARE
  v_member RECORD;
BEGIN
  -- 获取会员信息
  SELECT *
  INTO v_member
  FROM members
  WHERE id = p_member_id;

  -- 记录验证日志
  PERFORM log_debug(
    'check_member_exists',
    CASE WHEN FOUND THEN '会员验证成功' ELSE '会员不存在' END,
    jsonb_build_object(
      'member_id', p_member_id,
      'exists', FOUND,
      'details', CASE 
        WHEN FOUND THEN jsonb_build_object(
          'name', v_member.name,
          'email', v_member.email,
          'is_new_member', v_member.is_new_member,
          'created_at', v_member.created_at
        )
        ELSE NULL
      END
    )
  );

  RETURN FOUND;
END;
$$;


ALTER FUNCTION public.check_member_exists(p_member_id uuid) OWNER TO postgres;

--
-- Name: check_monthly_card_daily_limit(uuid, uuid, date); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.check_monthly_card_daily_limit(p_member_id uuid, p_card_id uuid, p_date date) RETURNS boolean
    LANGUAGE plpgsql
    AS $$
DECLARE
  v_card RECORD;
  v_daily_check_ins INTEGER;
BEGIN
  -- 获取会员卡信息
  SELECT * INTO v_card FROM membership_cards WHERE id = p_card_id;
  
  IF NOT FOUND THEN
    RETURN FALSE;
  END IF;
  
  -- 如果不是月卡，直接返回true
  IF v_card.card_type != '团课' OR v_card.card_category != '月卡' THEN
    RETURN TRUE;
  END IF;
  
  -- 获取当天非额外签到的次数
  SELECT COUNT(*) INTO v_daily_check_ins 
  FROM check_ins 
  WHERE member_id = p_member_id 
  AND check_in_date = p_date 
  AND NOT is_extra;
  
  -- 根据月卡类型检查每日签到次数限制
  IF v_card.card_subtype = '单次月卡' AND v_daily_check_ins >= 1 THEN
    RETURN FALSE;
  ELSIF v_card.card_subtype = '双次月卡' AND v_daily_check_ins >= 2 THEN
    RETURN FALSE;
  END IF;
  
  RETURN TRUE;
END;
$$;


ALTER FUNCTION public.check_monthly_card_daily_limit(p_member_id uuid, p_card_id uuid, p_date date) OWNER TO postgres;

--
-- Name: check_trainer_level_match(text, text); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.check_trainer_level_match(p_card_trainer_type text, p_trainer_type text) RETURNS boolean
    LANGUAGE plpgsql
    AS $$
BEGIN
  -- 如果会员卡要求高级教练，但实际教练是初级，返回false
  IF p_card_trainer_type = 'senior' AND p_trainer_type = 'jr' THEN
    RETURN FALSE;
  END IF;

  -- 其他情况都返回true
  RETURN TRUE;
END;
$$;


ALTER FUNCTION public.check_trainer_level_match(p_card_trainer_type text, p_trainer_type text) OWNER TO postgres;

--
-- Name: check_valid_cards(uuid, text, uuid); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.check_valid_cards(p_member_id uuid, p_card_type text, p_current_card_id uuid DEFAULT NULL::uuid) RETURNS boolean
    LANGUAGE plpgsql
    AS $$
DECLARE
  v_existing_card_id UUID;
BEGIN
  -- 查找除了当前卡之外的其他有效卡
  SELECT id INTO v_existing_card_id
  FROM membership_cards
  WHERE member_id = p_member_id
    AND card_type = p_card_type
    AND id != COALESCE(p_current_card_id, '00000000-0000-0000-0000-000000000000'::UUID)
    AND (valid_until IS NULL OR valid_until >= CURRENT_DATE)
    AND (
      (card_type = '团课' AND (
        (card_category = '课时卡' AND remaining_group_sessions > 0) OR
        card_category = '月卡'
      )) OR
      (card_type = '私教课' AND remaining_private_sessions > 0)
    );

  -- 记录检查结果
  PERFORM log_debug(
    'check_valid_cards',
    '检查有效卡',
    jsonb_build_object(
      'member_id', p_member_id,
      'card_type', p_card_type,
      'current_card_id', p_current_card_id,
      'existing_card_id', v_existing_card_id,
      'has_valid_card', v_existing_card_id IS NOT NULL
    )
  );

  RETURN v_existing_card_id IS NULL;
END;
$$;


ALTER FUNCTION public.check_valid_cards(p_member_id uuid, p_card_type text, p_current_card_id uuid) OWNER TO postgres;

--
-- Name: convert_time_slot_to_class_type(text); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.convert_time_slot_to_class_type(p_time_slot text) RETURNS public.class_type
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
BEGIN
  RETURN CASE 
    WHEN p_time_slot = '09:00-10:30' THEN 'morning'::class_type
    WHEN p_time_slot = '17:00-18:30' THEN 'evening'::class_type
    ELSE 'morning'::class_type  -- Default to morning for private classes
  END;
END;
$$;


ALTER FUNCTION public.convert_time_slot_to_class_type(p_time_slot text) OWNER TO postgres;

--
-- Name: create_new_member(text, text, public.class_type); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.create_new_member(p_name text, p_email text, p_class_type public.class_type) RETURNS json
    LANGUAGE plpgsql
    AS $$
DECLARE
  v_member_id uuid;
  v_check_in_id uuid;
BEGIN
  -- Start transaction
  BEGIN
    -- Check for existing member with same name
    IF EXISTS (
      SELECT 1 FROM members 
      WHERE LOWER(TRIM(name)) = LOWER(TRIM(p_name))
    ) THEN
      RAISE EXCEPTION 'Member already exists'
        USING HINT = 'member_exists';
    END IF;

    -- Create new member
    INSERT INTO members (
      name,
      email,
      is_new_member
    ) VALUES (
      TRIM(p_name),
      TRIM(p_email),
      true
    ) RETURNING id INTO v_member_id;

    -- Create initial check-in
    INSERT INTO check_ins (
      member_id,
      class_type,
      is_extra
    ) VALUES (
      v_member_id,
      p_class_type,
      true
    ) RETURNING id INTO v_check_in_id;

    -- Return success response
    RETURN json_build_object(
      'success', true,
      'member_id', v_member_id,
      'check_in_id', v_check_in_id
    );
  EXCEPTION
    WHEN OTHERS THEN
      -- Rollback will happen automatically
      RAISE;
  END;
END;
$$;


ALTER FUNCTION public.create_new_member(p_name text, p_email text, p_class_type public.class_type) OWNER TO postgres;

--
-- Name: deduct_membership_sessions(uuid, text, boolean, boolean); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.deduct_membership_sessions(p_card_id uuid, p_class_type text, p_is_private boolean DEFAULT false, p_is_1v2 boolean DEFAULT false) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
  v_card RECORD;
  v_deduct_sessions INTEGER;
BEGIN
  -- 锁定会员卡记录
  SELECT * INTO v_card 
  FROM membership_cards 
  WHERE id = p_card_id 
  FOR UPDATE;
  
  IF NOT FOUND THEN
    RAISE EXCEPTION '会员卡不存在';
  END IF;

  -- 记录开始扣除课时
  PERFORM log_debug(
    'deduct_membership_sessions',
    '开始扣除课时',
    jsonb_build_object(
      'card_id', p_card_id,
      'class_type', p_class_type,
      'is_private', p_is_private,
      'is_1v2', p_is_1v2,
      'card_type', v_card.card_type,
      'card_category', v_card.card_category,
      'remaining_private_sessions', v_card.remaining_private_sessions,
      'remaining_group_sessions', v_card.remaining_group_sessions
    )
  );
  
  -- 根据课程类型扣除课时
  IF NOT p_is_private AND p_class_type IN ('morning', 'evening') AND v_card.card_type = '团课' AND v_card.card_category = '课时卡' THEN
    -- 团课扣除1次课时
    v_deduct_sessions := 1;
    
    -- 检查剩余课时是否足够
    IF v_card.remaining_group_sessions < v_deduct_sessions THEN
      RAISE EXCEPTION '团课课时不足';
    END IF;
    
    UPDATE membership_cards 
    SET remaining_group_sessions = remaining_group_sessions - v_deduct_sessions
    WHERE id = p_card_id;
    
  ELSIF p_is_private AND v_card.card_type = '私教课' THEN
    -- 私教课统一扣除1次课时（1对1和1对2都一样）
    v_deduct_sessions := 1;
    
    -- 检查剩余课时是否足够
    IF v_card.remaining_private_sessions < v_deduct_sessions THEN
      RAISE EXCEPTION '私教课时不足';
    END IF;
    
    UPDATE membership_cards 
    SET remaining_private_sessions = remaining_private_sessions - v_deduct_sessions
    WHERE id = p_card_id;
  END IF;
  
  -- 记录扣除课时完成
  PERFORM log_debug(
    'deduct_membership_sessions',
    '扣除课时完成',
    jsonb_build_object(
      'card_id', p_card_id,
      'deducted_sessions', v_deduct_sessions,
      'remaining_private_sessions', CASE 
        WHEN p_is_private THEN v_card.remaining_private_sessions - v_deduct_sessions
        ELSE v_card.remaining_private_sessions
      END,
      'remaining_group_sessions', CASE
        WHEN NOT p_is_private THEN v_card.remaining_group_sessions - v_deduct_sessions
        ELSE v_card.remaining_group_sessions
      END
    )
  );
END;
$$;


ALTER FUNCTION public.deduct_membership_sessions(p_card_id uuid, p_class_type text, p_is_private boolean, p_is_1v2 boolean) OWNER TO postgres;

--
-- Name: delete_member(uuid); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.delete_member(p_member_id uuid) RETURNS boolean
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
BEGIN
    -- 调用级联删除函数
    PERFORM delete_member_cascade(p_member_id);
    RETURN TRUE;
EXCEPTION
    WHEN OTHERS THEN
        RETURN FALSE;
END;
$$;


ALTER FUNCTION public.delete_member(p_member_id uuid) OWNER TO postgres;

--
-- Name: FUNCTION delete_member(p_member_id uuid); Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON FUNCTION public.delete_member(p_member_id uuid) IS '删除会员的API函数，供前端调用';


--
-- Name: delete_member_cascade(uuid); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.delete_member_cascade(p_member_id uuid) RETURNS void
    LANGUAGE plpgsql
    AS $$
BEGIN
    -- 记录开始删除会员
    INSERT INTO debug_logs (function_name, message, details)
    VALUES ('delete_member_cascade', '开始删除会员及相关数据',
        jsonb_build_object(
            'member_id', p_member_id
        )
    );
    
    -- 删除会员的会员卡
    DELETE FROM membership_cards
    WHERE member_id = p_member_id;
    
    -- 删除会员的签到记录（会自动级联删除check_in_logs中的记录）
    DELETE FROM check_ins
    WHERE member_id = p_member_id;
    
    -- 最后删除会员记录
    DELETE FROM members
    WHERE id = p_member_id;
    
    -- 记录删除完成
    INSERT INTO debug_logs (function_name, message, details)
    VALUES ('delete_member_cascade', '会员及相关数据删除完成',
        jsonb_build_object(
            'member_id', p_member_id
        )
    );
EXCEPTION
    WHEN OTHERS THEN
        -- 记录删除失败
        INSERT INTO debug_logs (function_name, message, details)
        VALUES ('delete_member_cascade', '删除会员失败',
            jsonb_build_object(
                'member_id', p_member_id,
                'error', SQLERRM,
                'error_detail', SQLSTATE
            )
        );
        RAISE;
END;
$$;


ALTER FUNCTION public.delete_member_cascade(p_member_id uuid) OWNER TO postgres;

--
-- Name: FUNCTION delete_member_cascade(p_member_id uuid); Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON FUNCTION public.delete_member_cascade(p_member_id uuid) IS '级联删除会员及其相关数据，包括会员卡、签到记录和签到日志';


--
-- Name: find_member_for_checkin(text, text); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.find_member_for_checkin(p_name text, p_email text) RETURNS TABLE(member_id uuid, is_new boolean, needs_email boolean)
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
DECLARE
    v_normalized_name text;
    v_normalized_email text;
    v_base_email text;
    v_email_username text;
    v_email_domain text;
    v_found boolean := false;
BEGIN
    -- Input validation
    IF TRIM(p_name) = '' THEN
        RAISE EXCEPTION 'Name cannot be empty';
    END IF;

    -- Normalize inputs
    v_normalized_name := LOWER(TRIM(p_name));
    v_normalized_email := LOWER(TRIM(p_email));

    -- 提取邮箱的用户名和域名部分
    IF v_normalized_email IS NOT NULL AND v_normalized_email LIKE '%@%' THEN
        v_email_username := SPLIT_PART(v_normalized_email, '@', 1);
        v_email_domain := SPLIT_PART(v_normalized_email, '@', 2);
        
        -- 处理邮箱别名 (user+tag@domain.com)
        IF v_email_username LIKE '%+%' THEN
            v_base_email := SPLIT_PART(v_email_username, '+', 1) || '@' || v_email_domain;
        ELSE
            v_base_email := v_normalized_email;
        END IF;
    ELSE
        v_base_email := v_normalized_email;
    END IF;

    -- 记录调试信息
    RAISE NOTICE 'Email matching: original=%, normalized=%, base=%', 
        p_email, v_normalized_email, v_base_email;

    -- 首先尝试使用精确匹配
    FOR member_id, is_new, needs_email IN
        SELECT
            m.id,
            m.is_new_member,
            false AS needs_email
        FROM members m
        WHERE LOWER(TRIM(m.name)) = v_normalized_name
        AND (
            -- 精确匹配邮箱
            LOWER(TRIM(m.email)) = v_normalized_email
            OR
            -- 如果提供了邮箱，尝试匹配基本邮箱（去除+标签部分）
            (v_normalized_email IS NOT NULL AND v_base_email != v_normalized_email AND v_base_email = LOWER(TRIM(m.email)))
            OR
            -- 反向匹配：数据库中存储的是带+的邮箱，而用户输入的是基本邮箱
            (v_normalized_email IS NOT NULL AND
             LOWER(TRIM(m.email)) LIKE '%+%@%' AND
             SPLIT_PART(SPLIT_PART(LOWER(TRIM(m.email)), '@', 1), '+', 1) || '@' || SPLIT_PART(LOWER(TRIM(m.email)), '@', 2) = v_normalized_email)
            OR
            -- 特殊情况：hongyi+jhholy@hotmail.com 与 jhholy@hotmail.com 匹配
            (v_normalized_email LIKE 'hongyi+%@hotmail.com' AND
             LOWER(TRIM(m.email)) = 'jhholy@hotmail.com')
            OR
            -- 特殊情况：jhholy@hotmail.com 与 hongyi+jhholy@hotmail.com 匹配
            (v_normalized_email = 'jhholy@hotmail.com' AND
             LOWER(TRIM(m.email)) LIKE 'hongyi+%@hotmail.com')
        )
    LOOP
        v_found := true;
        RETURN NEXT;
    END LOOP;

    -- 如果找到记录，直接返回
    IF v_found THEN
        RETURN;
    END IF;

    -- 如果没有找到精确匹配，但提供了邮箱，检查是否有同名会员
    IF v_normalized_email IS NOT NULL THEN
        RETURN QUERY
        SELECT
            NULL::uuid AS member_id,
            true AS is_new,
            EXISTS (
                SELECT 1 FROM members
                WHERE LOWER(TRIM(name)) = v_normalized_name
            ) AS needs_email;
        RETURN;
    END IF;

    -- 如果没有找到记录，返回null和true表示新会员
    RETURN QUERY SELECT NULL::uuid, true::boolean, false::boolean;
END;
$$;


ALTER FUNCTION public.find_member_for_checkin(p_name text, p_email text) OWNER TO postgres;

--
-- Name: FUNCTION find_member_for_checkin(p_name text, p_email text); Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON FUNCTION public.find_member_for_checkin(p_name text, p_email text) IS 'Finds a member for check-in by name and email, with support for email aliases (user+tag@domain.com)';


--
-- Name: find_valid_card_for_checkin(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.find_valid_card_for_checkin() RETURNS trigger
    LANGUAGE plpgsql
    AS $$ DECLARE v_card_id UUID; v_card_type TEXT; v_class_type TEXT := NEW.class_type; v_is_private BOOLEAN := NEW.is_private; BEGIN IF NEW.card_id IS NOT NULL THEN RETURN NEW; END IF; PERFORM log_debug('find_valid_card_for_checkin', '开始查找有效会员卡', jsonb_build_object('member_id', NEW.member_id, 'class_type', v_class_type, 'is_private', v_is_private)); IF v_is_private THEN v_card_type := '私教课'; ELSE v_card_type := '团课'; END IF; SELECT id INTO v_card_id FROM membership_cards WHERE member_id = NEW.member_id AND ((v_is_private AND card_type = '私教课' AND (remaining_private_sessions IS NULL OR remaining_private_sessions > 0)) OR (NOT v_is_private AND card_type = '团课' AND ((card_category = '课时卡' AND (remaining_group_sessions IS NULL OR remaining_group_sessions > 0)) OR card_category = '月卡'))) AND (valid_until IS NULL OR valid_until >= NEW.check_in_date) ORDER BY CASE WHEN card_category = '课时卡' THEN 0 ELSE 1 END, CASE WHEN valid_until IS NOT NULL THEN valid_until ELSE '9999-12-31'::DATE END LIMIT 1; IF v_card_id IS NOT NULL THEN NEW.card_id = v_card_id; NEW.is_extra = false; PERFORM log_debug('find_valid_card_for_checkin', '找到有效会员卡', jsonb_build_object('member_id', NEW.member_id, 'card_id', v_card_id)); ELSE PERFORM log_debug('find_valid_card_for_checkin', '未找到有效会员卡', jsonb_build_object('member_id', NEW.member_id)); NEW.is_extra = true; END IF; RETURN NEW; END; $$;


ALTER FUNCTION public.find_valid_card_for_checkin() OWNER TO postgres;

--
-- Name: fix_member_extra_checkins(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.fix_member_extra_checkins() RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
    v_member_id UUID;
    v_actual_count INTEGER;
    v_current_count INTEGER;
    v_updated_count INTEGER := 0;
BEGIN
    -- 记录开始修复
    INSERT INTO debug_logs (function_name, message, details)
    VALUES (
        'fix_member_extra_checkins',
        '开始修复会员额外签到计数',
        jsonb_build_object('timestamp', NOW())
    );
    
    -- 遍历所有会员
    FOR v_member_id, v_current_count IN 
        SELECT id, COALESCE(extra_check_ins, 0) 
        FROM members
    LOOP
        -- 计算实际的额外签到次数
        SELECT COUNT(*) INTO v_actual_count
        FROM check_ins
        WHERE member_id = v_member_id AND is_extra = true;
        
        -- 如果计数不一致，则更新
        IF v_current_count != v_actual_count THEN
            UPDATE members
            SET extra_check_ins = v_actual_count
            WHERE id = v_member_id;
            
            v_updated_count := v_updated_count + 1;
            
            -- 记录更新信息
            INSERT INTO debug_logs (function_name, member_id, message, details)
            VALUES (
                'fix_member_extra_checkins',
                v_member_id,
                '修复会员额外签到计数',
                jsonb_build_object(
                    'old_count', v_current_count,
                    'new_count', v_actual_count,
                    'difference', v_actual_count - v_current_count
                )
            );
        END IF;
    END LOOP;
    
    -- 记录完成修复
    INSERT INTO debug_logs (function_name, message, details)
    VALUES (
        'fix_member_extra_checkins',
        '完成修复会员额外签到计数',
        jsonb_build_object(
            'updated_members', v_updated_count,
            'timestamp', NOW()
        )
    );
END;
$$;


ALTER FUNCTION public.fix_member_extra_checkins() OWNER TO postgres;

--
-- Name: generate_mock_check_ins(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.generate_mock_check_ins() RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
    v_member_id UUID;
    v_card_id UUID;
    v_trainer_id UUID;
    v_check_in_date DATE;
    v_class_type TEXT;
    v_time_slot TEXT;
    v_is_private BOOLEAN;
    v_is_extra BOOLEAN;
    v_is_1v2 BOOLEAN;
    v_class_time TIME;
    v_senior_trainer_ids UUID[];
    v_jr_trainer_id UUID;
    v_random_number INT;
    v_count INT := 0;
BEGIN
    -- 获取教练ID
    SELECT array_agg(id) INTO v_senior_trainer_ids FROM trainers WHERE type = 'senior';
    SELECT id INTO v_jr_trainer_id FROM trainers WHERE type = 'jr' LIMIT 1;
    
    -- 禁用触发器以避免扣除课时等操作
    ALTER TABLE check_ins DISABLE TRIGGER ALL;
    
    -- 生成约100条签到记录
    WHILE v_count < 100 LOOP
        -- 随机选择会员
        SELECT id INTO v_member_id FROM members ORDER BY random() LIMIT 1;
        
        -- 随机选择会员卡
        SELECT id INTO v_card_id FROM membership_cards WHERE member_id = v_member_id ORDER BY random() LIMIT 1;
        
        -- 随机生成过去一个月内的日期
        v_check_in_date := current_date - (random() * 30)::integer;
        
        -- 随机决定是团课还是私教课
        v_random_number := floor(random() * 10);
        
        IF v_random_number < 7 THEN
            -- 70%概率是团课
            v_is_private := FALSE;
            
            -- 随机决定是早课还是晚课
            IF random() < 0.5 THEN
                v_class_type := 'morning';
                v_time_slot := '09:00-10:30';
                v_class_time := '09:00:00'::TIME;
            ELSE
                v_class_type := 'evening';
                v_time_slot := '17:00-18:30';
                v_class_time := '17:00:00'::TIME;
            END IF;
            
            v_trainer_id := NULL;
            v_is_1v2 := FALSE;
        ELSE
            -- 30%概率是私教课
            v_is_private := TRUE;
            v_class_type := 'private';
            
            -- 随机选择教练
            IF random() < 0.8 THEN
                -- 80%概率选择高级教练
                v_trainer_id := v_senior_trainer_ids[1 + floor(random() * array_length(v_senior_trainer_ids, 1))];
            ELSE
                -- 20%概率选择JR教练
                v_trainer_id := v_jr_trainer_id;
            END IF;
            
            -- 随机决定是否为1对2私教
            v_is_1v2 := random() < 0.2; -- 20%概率是1对2私教
            
            -- 随机选择私教时段
            v_random_number := floor(random() * 6);
            CASE v_random_number
                WHEN 0 THEN v_time_slot := '10:30-11:30'; v_class_time := '10:30:00'::TIME;
                WHEN 1 THEN v_time_slot := '11:30-12:30'; v_class_time := '11:30:00'::TIME;
                WHEN 2 THEN v_time_slot := '14:00-15:00'; v_class_time := '14:00:00'::TIME;
                WHEN 3 THEN v_time_slot := '15:00-16:00'; v_class_time := '15:00:00'::TIME;
                WHEN 4 THEN v_time_slot := '16:00-17:00'; v_class_time := '16:00:00'::TIME;
                WHEN 5 THEN v_time_slot := '19:00-20:00'; v_class_time := '19:00:00'::TIME;
            END CASE;
        END IF;
        
        -- 随机决定是否为额外签到
        v_is_extra := random() < 0.3; -- 30%概率是额外签到
        
        -- 检查是否已存在相同会员同一天同一时段的签到
        IF NOT EXISTS (
            SELECT 1 FROM check_ins 
            WHERE member_id = v_member_id 
            AND check_in_date = v_check_in_date 
            AND time_slot = v_time_slot
        ) THEN
            -- 插入签到记录
            INSERT INTO check_ins (
                member_id, 
                check_in_date, 
                is_extra, 
                trainer_id, 
                is_1v2, 
                class_time, 
                card_id, 
                is_private, 
                time_slot, 
                class_type
            ) VALUES (
                v_member_id, 
                v_check_in_date, 
                v_is_extra, 
                v_trainer_id, 
                v_is_1v2, 
                v_class_time, 
                v_card_id, 
                v_is_private, 
                v_time_slot, 
                v_class_type::class_type
            );
            
            v_count := v_count + 1;
        END IF;
    END LOOP;
    
    -- 重新启用触发器
    ALTER TABLE check_ins ENABLE TRIGGER ALL;
    
    RAISE NOTICE '成功生成 % 条模拟签到记录', v_count;
END;
$$;


ALTER FUNCTION public.generate_mock_check_ins() OWNER TO postgres;

--
-- Name: get_class_type_from_time_slot(text); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.get_class_type_from_time_slot(p_time_slot text) RETURNS public.class_type
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
BEGIN
  RETURN CASE 
    WHEN p_time_slot = '09:00-10:30' THEN 'morning'::class_type
    WHEN p_time_slot = '17:00-18:30' THEN 'evening'::class_type
    ELSE 'morning'::class_type  -- Default to morning for private classes
  END;
END;
$$;


ALTER FUNCTION public.get_class_type_from_time_slot(p_time_slot text) OWNER TO postgres;

--
-- Name: get_valid_time_slot(text); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.get_valid_time_slot(p_class_type text) RETURNS text
    LANGUAGE plpgsql
    AS $$
BEGIN
  -- 根据课程类型返回默认时间段
  RETURN CASE 
    WHEN p_class_type = 'morning' THEN '09:00-10:30'
    WHEN p_class_type = 'evening' THEN '17:00-18:30'
    WHEN p_class_type = 'private' THEN '10:30-11:30'
    ELSE '09:00-10:30'  -- 默认时间段
  END;
END;
$$;


ALTER FUNCTION public.get_valid_time_slot(p_class_type text) OWNER TO postgres;

--
-- Name: handle_check_in(uuid, text, text, text, date, uuid, uuid, boolean, text); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.handle_check_in(p_member_id uuid, p_name text, p_email text, p_class_type text, p_check_in_date date, p_card_id uuid DEFAULT NULL::uuid, p_trainer_id uuid DEFAULT NULL::uuid, p_is_1v2 boolean DEFAULT false, p_time_slot text DEFAULT NULL::text) RETURNS jsonb
    LANGUAGE plpgsql
    AS $$ DECLARE v_is_duplicate boolean; v_is_extra boolean; v_check_in_id uuid; v_class_type class_type; v_card_validity jsonb; v_is_new_member boolean := false; v_is_private boolean; BEGIN PERFORM log_debug('handle_check_in', '开始处理签到', jsonb_build_object('member_id', p_member_id, 'name', p_name, 'email', p_email, 'class_type', p_class_type, 'check_in_date', p_check_in_date, 'card_id', p_card_id, 'trainer_id', p_trainer_id, 'is_1v2', p_is_1v2, 'time_slot', p_time_slot)); BEGIN v_class_type := p_class_type::class_type; v_is_private := (v_class_type = 'private'); EXCEPTION WHEN OTHERS THEN PERFORM log_debug('handle_check_in', '无效的课程类型', jsonb_build_object('class_type', p_class_type, 'error', SQLERRM)); RETURN jsonb_build_object('success', false, 'message', '无效的课程类型: ' || p_class_type, 'error', SQLERRM); END; IF p_time_slot IS NULL THEN PERFORM log_debug('handle_check_in', '缺少时间段', jsonb_build_object('member_id', p_member_id, 'class_type', p_class_type)); RETURN jsonb_build_object('success', false, 'message', '请选择有效的时间段', 'error', 'time_slot_required'); END IF; BEGIN IF NOT check_member_exists(p_member_id) THEN INSERT INTO members(id, name, email, is_new_member) VALUES (p_member_id, p_name, p_email, true); v_is_extra := true; v_is_new_member := true; PERFORM log_debug('handle_check_in', '创建新会员', jsonb_build_object('member_id', p_member_id, 'name', p_name, 'email', p_email)); END IF; v_is_duplicate := check_duplicate_check_in(p_member_id, p_check_in_date, p_class_type, p_time_slot); IF v_is_duplicate THEN PERFORM log_debug('handle_check_in', '发现重复签到但允许继续', jsonb_build_object('member_id', p_member_id, 'class_type', p_class_type, 'time_slot', p_time_slot)); END IF; IF p_card_id IS NOT NULL THEN v_card_validity := check_card_validity(p_card_id, p_member_id, p_class_type, p_check_in_date, p_trainer_id); IF (v_card_validity->>'is_valid')::boolean THEN v_is_extra := false; ELSE v_is_extra := true; PERFORM log_debug('handle_check_in', '会员卡验证失败', jsonb_build_object('reason', v_card_validity->>'reason', 'details', v_card_validity->'details')); END IF; ELSE v_is_extra := true; PERFORM log_debug('handle_check_in', '未指定会员卡', jsonb_build_object('member_id', p_member_id, 'class_type', p_class_type)); END IF; INSERT INTO check_ins(member_id, card_id, class_type, check_in_date, trainer_id, is_1v2, is_extra, time_slot, is_private) VALUES (p_member_id, p_card_id, v_class_type, p_check_in_date, CASE WHEN v_is_private THEN p_trainer_id ELSE NULL END, CASE WHEN v_is_private THEN p_is_1v2 ELSE false END, v_is_extra, p_time_slot, v_is_private) RETURNING id INTO v_check_in_id; UPDATE members SET extra_check_ins = CASE WHEN v_is_extra THEN extra_check_ins + 1 ELSE extra_check_ins END, last_check_in_date = p_check_in_date WHERE id = p_member_id; IF NOT v_is_extra AND p_card_id IS NOT NULL THEN PERFORM deduct_membership_sessions(p_card_id, p_class_type, v_is_private); END IF; PERFORM log_debug('handle_check_in', '签到完成', jsonb_build_object('check_in_id', v_check_in_id, 'member_id', p_member_id, 'card_id', p_card_id, 'class_type', v_class_type, 'is_extra', v_is_extra, 'is_new_member', v_is_new_member)); RETURN jsonb_build_object('success', true, 'check_in_id', v_check_in_id, 'is_extra', v_is_extra, 'is_new_member', v_is_new_member); EXCEPTION WHEN OTHERS THEN PERFORM log_debug('handle_check_in', '签到失败', jsonb_build_object('member_id', p_member_id, 'error', SQLERRM, 'details', jsonb_build_object('class_type', p_class_type, 'check_in_date', p_check_in_date, 'card_id', p_card_id))); RETURN jsonb_build_object('success', false, 'message', SQLERRM, 'error', SQLERRM); END; END; $$;


ALTER FUNCTION public.handle_check_in(p_member_id uuid, p_name text, p_email text, p_class_type text, p_check_in_date date, p_card_id uuid, p_trainer_id uuid, p_is_1v2 boolean, p_time_slot text) OWNER TO postgres;

--
-- Name: init_check_in_session(uuid, public.class_type); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.init_check_in_session(member_id uuid, class_type_param public.class_type) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    member_record members%ROWTYPE;
    result JSONB;
BEGIN
    -- 获取会员信息
    SELECT * INTO member_record
    FROM members
    WHERE id = member_id;
    
    IF member_record IS NULL THEN
        RAISE EXCEPTION 'Member not found';
    END IF;
    
    -- 构建返回结果
    result := jsonb_build_object(
        'member_id', member_record.id,
        'name', member_record.name,
        'remaining_classes', member_record.remaining_classes,
        'membership', member_record.membership,
        'last_check_in_date', member_record.last_check_in_date,
        'daily_check_ins', member_record.daily_check_ins,
        'extra_check_ins', member_record.extra_check_ins,
        'class_type', class_type_param
    );
    
    RETURN result;
END;
$$;


ALTER FUNCTION public.init_check_in_session(member_id uuid, class_type_param public.class_type) OWNER TO postgres;

--
-- Name: log_debug(text, text, jsonb, uuid); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.log_debug(p_function_name text, p_message text, p_details jsonb, p_member_id uuid DEFAULT NULL::uuid) RETURNS void
    LANGUAGE plpgsql
    AS $$
BEGIN
  IF current_setting('app.environment', true) = 'development' THEN
    INSERT INTO debug_logs (function_name, message, details, member_id)
    VALUES (p_function_name, p_message, p_details, p_member_id);
  END IF;
END;
$$;


ALTER FUNCTION public.log_debug(p_function_name text, p_message text, p_details jsonb, p_member_id uuid) OWNER TO postgres;

--
-- Name: FUNCTION log_debug(p_function_name text, p_message text, p_details jsonb, p_member_id uuid); Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON FUNCTION public.log_debug(p_function_name text, p_message text, p_details jsonb, p_member_id uuid) IS '通用的日志记录函数，简化各个函数中的日志记录代码';


--
-- Name: process_check_in(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.process_check_in() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
DECLARE
    v_member_id uuid;
    v_card_id uuid;
    v_debug_details jsonb;
BEGIN
    -- 设置时区
    SET TIME ZONE 'Asia/Bangkok';
    
    -- 获取会员ID和卡ID
    v_member_id := NEW.member_id;
    v_card_id := NEW.card_id;
    
    -- 初始化调试信息
    v_debug_details := jsonb_build_object(
        'member_id', v_member_id,
        'check_in_date', NEW.check_in_date,
        'class_type', NEW.class_type,
        'is_extra', NEW.is_extra,
        'card_id', v_card_id
    );

    -- 处理正常签到（有效会员卡）
    IF NOT NEW.is_extra THEN
        -- 更新会员卡剩余次数
        UPDATE membership_cards
        SET 
            remaining_group_sessions = CASE 
                WHEN card_type = 'group' AND card_category = 'sessions' 
                AND NEW.class_type IN ('morning', 'evening')
                THEN remaining_group_sessions - 1
                ELSE remaining_group_sessions
            END,
            remaining_private_sessions = CASE 
                WHEN card_type = 'private' AND NEW.class_type = 'private'
                THEN remaining_private_sessions - 1
                ELSE remaining_private_sessions
            END
        WHERE id = v_card_id;

        -- 记录调试信息
        INSERT INTO debug_logs (function_name, message, details, member_id)
        VALUES (
            'process_check_in',
            '正常签到处理完成',
            jsonb_build_object(
                'action', '更新会员卡剩余次数',
                'check_details', v_debug_details
            ),
            v_member_id
        );
    ELSE
        -- 更新会员的额外签到统计
        UPDATE members
        SET extra_check_ins = COALESCE(extra_check_ins, 0) + 1
        WHERE id = v_member_id;

        -- 记录调试信息
        INSERT INTO debug_logs (function_name, message, details, member_id)
        VALUES (
            'process_check_in',
            '额外签到处理完成',
            jsonb_build_object(
                'action', '更新额外签到统计',
                'check_details', v_debug_details
            ),
            v_member_id
        );
    END IF;

    -- 更新会员最后签到日期
    UPDATE members
    SET last_check_in_date = NEW.check_in_date
    WHERE id = v_member_id;

    -- 记录最终调试信息
    INSERT INTO debug_logs (function_name, message, details, member_id)
    VALUES (
        'process_check_in',
        '签到处理完成',
        jsonb_build_object(
            'final_status', '成功',
            'check_details', v_debug_details
        ),
        v_member_id
    );

    RETURN NEW;
END;
$$;


ALTER FUNCTION public.process_check_in() OWNER TO postgres;

--
-- Name: register_new_member(text, text, text, boolean, uuid, boolean); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.register_new_member(p_name text, p_email text, p_time_slot text, p_is_private boolean DEFAULT false, p_trainer_id uuid DEFAULT NULL::uuid, p_is_1v2 boolean DEFAULT false) RETURNS json
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $_$
DECLARE
  v_member_id uuid;
  v_check_in_id uuid;
  v_existing_member RECORD;
  v_trainer_exists boolean;
BEGIN
  -- Input validation
  IF NOT validate_member_name(p_name) THEN
    RAISE EXCEPTION '无效的姓名格式。Invalid name format.'
      USING HINT = 'invalid_name';
  END IF;

  -- Email validation
  IF p_email IS NULL OR TRIM(p_email) = '' THEN
    RAISE EXCEPTION '邮箱是必填字段。Email is required.'
      USING HINT = 'email_required';
  END IF;

  -- Time slot validation
  IF p_time_slot IS NULL OR TRIM(p_time_slot) = '' THEN
    RAISE EXCEPTION '必须选择时段。Time slot is required.'
      USING HINT = 'time_slot_required';
  END IF;

  -- Basic time slot format validation
  IF p_time_slot !~ '^\d{2}:\d{2}-\d{2}:\d{2}$' THEN
    RAISE EXCEPTION '无效的时间段格式。Invalid time slot format.'
      USING HINT = 'invalid_time_slot_format';
  END IF;

  -- Private class validation
  IF p_is_private THEN
    -- Validate trainer
    IF p_trainer_id IS NULL THEN
      RAISE EXCEPTION '私教课程必须选择教练。Trainer is required for private class.'
        USING HINT = 'trainer_required';
    END IF;

    -- Check if trainer exists
    SELECT EXISTS (
      SELECT 1 FROM trainers WHERE id = p_trainer_id
    ) INTO v_trainer_exists;

    IF NOT v_trainer_exists THEN
      RAISE EXCEPTION '教练不存在。Trainer does not exist.'
        USING HINT = 'invalid_trainer';
    END IF;
  ELSE
    -- For group classes, validate time slot
    IF p_time_slot NOT IN ('09:00-10:30', '17:00-18:30') THEN
      RAISE EXCEPTION '无效的团课时段。Invalid group class time slot.'
        USING HINT = 'invalid_time_slot';
    END IF;
  END IF;

  -- Lock the members table for the specific name to prevent concurrent registrations
  PERFORM 1 
  FROM members 
  WHERE LOWER(TRIM(name)) = LOWER(TRIM(p_name))
  FOR UPDATE SKIP LOCKED;

  -- Check if member exists after acquiring lock
  SELECT id, email, is_new_member 
  INTO v_existing_member
  FROM members
  WHERE LOWER(TRIM(name)) = LOWER(TRIM(p_name));

  IF FOUND THEN
    RAISE EXCEPTION '该姓名已被注册。This name is already registered.'
      USING HINT = 'member_exists';
  END IF;

  -- Create new member
  INSERT INTO members (
    name,
    email,
    is_new_member,
    created_at
  ) VALUES (
    TRIM(p_name),
    TRIM(p_email),
    true,
    NOW()
  ) RETURNING id INTO v_member_id;

  -- Create initial check-in
  INSERT INTO check_ins (
    member_id,
    check_in_date,
    is_extra,
    is_private,
    trainer_id,
    time_slot,
    is_1v2,
    created_at,
    class_type  -- Include class_type based on time_slot
  ) VALUES (
    v_member_id,
    CURRENT_DATE,
    true,
    p_is_private,
    p_trainer_id,
    p_time_slot,
    p_is_1v2,
    NOW(),
    get_class_type_from_time_slot(p_time_slot)  -- Set class_type based on time_slot
  ) RETURNING id INTO v_check_in_id;

  RETURN json_build_object(
    'success', true,
    'member_id', v_member_id,
    'check_in_id', v_check_in_id
  );

EXCEPTION
  WHEN unique_violation THEN
    RAISE EXCEPTION '该邮箱已被注册。This email is already registered.'
      USING HINT = 'email_exists';
  WHEN OTHERS THEN
    RAISE EXCEPTION '%', SQLERRM;
END;
$_$;


ALTER FUNCTION public.register_new_member(p_name text, p_email text, p_time_slot text, p_is_private boolean, p_trainer_id uuid, p_is_1v2 boolean) OWNER TO postgres;

--
-- Name: search_member(text, boolean); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.search_member(search_term text, exact_match boolean DEFAULT false) RETURNS TABLE(id uuid, name text, email text, phone text, membership public.membership_type, remaining_classes integer, last_check_in_date date, is_new_member boolean, membership_expiry timestamp with time zone, daily_check_ins integer, extra_check_ins integer)
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
BEGIN
    RETURN QUERY
    SELECT 
        m.id, m.name, m.email, m.phone, m.membership, 
        m.remaining_classes, m.last_check_in_date, m.is_new_member,
        m.membership_expiry, m.daily_check_ins, m.extra_check_ins
    FROM members m
    WHERE 
        CASE 
            WHEN exact_match THEN 
                m.name = search_term
            ELSE 
                m.name ILIKE '%' || search_term || '%'
                OR m.email ILIKE '%' || search_term || '%'
                OR m.phone ILIKE '%' || search_term || '%'
        END
    ORDER BY 
        CASE WHEN m.name = search_term THEN 0
             WHEN m.name ILIKE search_term || '%' THEN 1
             ELSE 2
        END,
        m.name;
END;
$$;


ALTER FUNCTION public.search_member(search_term text, exact_match boolean) OWNER TO postgres;

--
-- Name: set_card_validity(uuid, text, text, text); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.set_card_validity(p_card_id uuid, p_card_type text, p_card_category text, p_card_subtype text) RETURNS date
    LANGUAGE plpgsql
    AS $$
DECLARE
  v_valid_until DATE;
BEGIN
  -- 根据不同卡类型设置有效期
  v_valid_until := CASE
    -- 团课月卡：购买日起30天
    WHEN (p_card_type = 'group' OR p_card_type = '团课') AND (p_card_category = 'monthly' OR p_card_category = '月卡') THEN
      CURRENT_DATE + INTERVAL '30 days'
    -- 团课10次卡：购买日起3个月
    WHEN (p_card_type = 'group' OR p_card_type = '团课') AND 
         ((p_card_category = 'session' OR p_card_category = '课时卡') AND 
          (p_card_subtype = 'ten_classes' OR p_card_subtype = '10次卡' OR p_card_subtype = '10_sessions')) THEN
      CURRENT_DATE + INTERVAL '3 months'
    -- 私教10次卡：购买日起1个月
    WHEN (p_card_type = 'private' OR p_card_type = '私教课') AND 
         (p_card_subtype = 'ten_classes' OR p_card_subtype = '10次卡' OR p_card_subtype = '10_sessions') THEN
      CURRENT_DATE + INTERVAL '1 month'
    -- 其他卡：无到期限制（包括团课单次卡、团课两次卡和私教单次卡）
    ELSE NULL
  END;

  -- 记录日志
  PERFORM log_debug(
    'set_card_validity',
    '设置会员卡有效期',
    jsonb_build_object(
      'card_id', p_card_id,
      'card_type', p_card_type,
      'card_category', p_card_category,
      'card_subtype', p_card_subtype,
      'valid_until', v_valid_until
    )
  );
  
  RETURN v_valid_until;
END;
$$;


ALTER FUNCTION public.set_card_validity(p_card_id uuid, p_card_type text, p_card_category text, p_card_subtype text) OWNER TO postgres;

--
-- Name: test_expired_card_validation(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.test_expired_card_validation() RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
    v_member_id UUID;
    v_card_id UUID;
    v_check_in_id UUID;
    v_is_extra BOOLEAN;
    v_test_date DATE := CURRENT_DATE + INTERVAL '1 day'; -- 使用明天的日期避免重复签到
BEGIN
    -- 创建测试会员
    INSERT INTO members (id, name, email, is_new_member)
    VALUES (gen_random_uuid(), '过期卡测试会员', 'expired_card_test@example.com', false)
    RETURNING id INTO v_member_id;
    
    -- 记录开始测试
    INSERT INTO debug_logs (function_name, message, details)
    VALUES (
        'test_expired_card_validation',
        '开始测试过期会员卡验证',
        jsonb_build_object(
            'timestamp', NOW(),
            'member_id', v_member_id,
            'test_date', v_test_date
        )
    );
    
    -- 创建过期会员卡
    INSERT INTO membership_cards (id, member_id, card_type, card_category, card_subtype, valid_until, remaining_group_sessions)
    VALUES (gen_random_uuid(), v_member_id, 'group', 'session', 'ten_sessions', v_test_date - INTERVAL '1 day', 5)
    RETURNING id INTO v_card_id;
    
    -- 创建签到记录（使用过期会员卡）
    INSERT INTO check_ins (id, member_id, card_id, check_in_date, class_type, is_private, time_slot)
    VALUES (gen_random_uuid(), v_member_id, v_card_id, v_test_date, 'morning', false, '09:00-10:30')
    RETURNING id, is_extra INTO v_check_in_id, v_is_extra;
    
    -- 记录测试结果
    INSERT INTO debug_logs (function_name, message, details)
    VALUES (
        'test_expired_card_validation',
        '过期会员卡签到测试结果',
        jsonb_build_object(
            'timestamp', NOW(),
            'member_id', v_member_id,
            'card_id', v_card_id,
            'check_in_id', v_check_in_id,
            'is_extra', v_is_extra,
            'expected_is_extra', true,
            'test_passed', v_is_extra = true
        )
    );
    
    -- 清理测试数据
    DELETE FROM check_ins WHERE member_id = v_member_id;
    DELETE FROM membership_cards WHERE member_id = v_member_id;
    DELETE FROM members WHERE id = v_member_id;
    
    -- 记录测试完成
    INSERT INTO debug_logs (function_name, message, details)
    VALUES (
        'test_expired_card_validation',
        '完成测试过期会员卡验证',
        jsonb_build_object(
            'timestamp', NOW()
        )
    );
END;
$$;


ALTER FUNCTION public.test_expired_card_validation() OWNER TO postgres;

--
-- Name: test_expired_card_validation_v2(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.test_expired_card_validation_v2() RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
    v_member_id UUID;
    v_card_id UUID;
    v_check_in_id UUID;
    v_is_extra BOOLEAN;
    v_test_date DATE := CURRENT_DATE + INTERVAL '1 day'; -- 使用明天的日期避免重复签到
BEGIN
    -- 创建测试会员
    INSERT INTO members (id, name, email, is_new_member)
    VALUES (gen_random_uuid(), '过期卡测试会员2', 'expired_card_test2@example.com', false)
    RETURNING id INTO v_member_id;
    
    -- 记录开始测试
    INSERT INTO debug_logs (function_name, message, details)
    VALUES (
        'test_expired_card_validation_v2',
        '开始测试过期会员卡验证（第二版）',
        jsonb_build_object(
            'timestamp', NOW(),
            'member_id', v_member_id,
            'test_date', v_test_date
        )
    );
    
    -- 创建过期会员卡（确保valid_until不为NULL）
    INSERT INTO membership_cards (id, member_id, card_type, card_category, card_subtype, valid_until, remaining_group_sessions)
    VALUES (gen_random_uuid(), v_member_id, 'group', 'session', 'ten_sessions', v_test_date - INTERVAL '1 day', 5)
    RETURNING id INTO v_card_id;
    
    -- 记录会员卡信息
    INSERT INTO debug_logs (function_name, message, details)
    VALUES (
        'test_expired_card_validation_v2',
        '创建过期会员卡',
        jsonb_build_object(
            'timestamp', NOW(),
            'member_id', v_member_id,
            'card_id', v_card_id,
            'valid_until', v_test_date - INTERVAL '1 day',
            'check_in_date', v_test_date
        )
    );
    
    -- 创建签到记录（使用过期会员卡）
    INSERT INTO check_ins (id, member_id, card_id, check_in_date, class_type, is_private, time_slot)
    VALUES (gen_random_uuid(), v_member_id, v_card_id, v_test_date, 'morning', false, '09:00-10:30')
    RETURNING id, is_extra INTO v_check_in_id, v_is_extra;
    
    -- 记录测试结果
    INSERT INTO debug_logs (function_name, message, details)
    VALUES (
        'test_expired_card_validation_v2',
        '过期会员卡签到测试结果',
        jsonb_build_object(
            'timestamp', NOW(),
            'member_id', v_member_id,
            'card_id', v_card_id,
            'check_in_id', v_check_in_id,
            'is_extra', v_is_extra,
            'expected_is_extra', true,
            'test_passed', v_is_extra = true
        )
    );
    
    -- 清理测试数据
    DELETE FROM check_ins WHERE member_id = v_member_id;
    DELETE FROM membership_cards WHERE member_id = v_member_id;
    DELETE FROM members WHERE id = v_member_id;
    
    -- 记录测试完成
    INSERT INTO debug_logs (function_name, message, details)
    VALUES (
        'test_expired_card_validation_v2',
        '完成测试过期会员卡验证（第二版）',
        jsonb_build_object(
            'timestamp', NOW()
        )
    );
END;
$$;


ALTER FUNCTION public.test_expired_card_validation_v2() OWNER TO postgres;

--
-- Name: trigger_deduct_sessions(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.trigger_deduct_sessions() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  -- 只有非额外签到才扣除课时
  IF NOT NEW.is_extra AND NEW.card_id IS NOT NULL THEN
    PERFORM deduct_membership_sessions(NEW.card_id, NEW.class_type::TEXT, NEW.is_private, NEW.is_1v2);
  END IF;
  
  RETURN NULL;
END;
$$;


ALTER FUNCTION public.trigger_deduct_sessions() OWNER TO postgres;

--
-- Name: trigger_set_card_validity(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.trigger_set_card_validity() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  NEW.valid_until := set_card_validity(NEW.id, NEW.card_type, NEW.card_category, NEW.card_subtype);
  RETURN NEW;
END;
$$;


ALTER FUNCTION public.trigger_set_card_validity() OWNER TO postgres;

--
-- Name: update_check_in_stats(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.update_check_in_stats() RETURNS trigger
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
BEGIN
  -- Update member's last check-in date
  UPDATE members
  SET last_check_in_date = NEW.check_in_date
  WHERE id = NEW.member_id;

  -- If it's an extra check-in, increment the counter
  IF NEW.is_extra THEN
    UPDATE members
    SET extra_check_ins = COALESCE(extra_check_ins, 0) + 1
    WHERE id = NEW.member_id;
  END IF;

  RETURN NEW;
END;
$$;


ALTER FUNCTION public.update_check_in_stats() OWNER TO postgres;

--
-- Name: update_member_extra_checkins(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.update_member_extra_checkins() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
DECLARE
    v_old_is_extra BOOLEAN;
BEGIN
    -- 获取旧记录的is_extra值（如果是更新操作）
    IF TG_OP = 'UPDATE' THEN
        v_old_is_extra := OLD.is_extra;
    ELSE
        v_old_is_extra := FALSE;
    END IF;
    
    -- 记录调试信息
    INSERT INTO debug_logs (function_name, member_id, message, details)
    VALUES (
        'update_member_extra_checkins',
        NEW.member_id,
        '更新会员额外签到计数',
        jsonb_build_object(
            'operation', TG_OP,
            'old_is_extra', v_old_is_extra,
            'new_is_extra', NEW.is_extra
        )
    );
    
    -- 根据操作类型和is_extra的变化更新会员的额外签到计数
    IF TG_OP = 'INSERT' AND NEW.is_extra THEN
        -- 新增额外签到
        UPDATE members
        SET extra_check_ins = COALESCE(extra_check_ins, 0) + 1
        WHERE id = NEW.member_id;
        
    ELSIF TG_OP = 'UPDATE' THEN
        IF NOT v_old_is_extra AND NEW.is_extra THEN
            -- 从普通签到变为额外签到
            UPDATE members
            SET extra_check_ins = COALESCE(extra_check_ins, 0) + 1
            WHERE id = NEW.member_id;
            
        ELSIF v_old_is_extra AND NOT NEW.is_extra THEN
            -- 从额外签到变为普通签到
            UPDATE members
            SET extra_check_ins = GREATEST(COALESCE(extra_check_ins, 0) - 1, 0)
            WHERE id = NEW.member_id;
        END IF;
    END IF;
    
    RETURN NEW;
END;
$$;


ALTER FUNCTION public.update_member_extra_checkins() OWNER TO postgres;

--
-- Name: update_member_status(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.update_member_status() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  -- 如果是新会员，更新为老会员
  IF (SELECT is_new_member FROM members WHERE id = NEW.member_id) THEN
    UPDATE members
    SET is_new_member = false
    WHERE id = NEW.member_id;
    
    -- 记录日志
    INSERT INTO debug_logs (function_name, message, member_id, details)
    VALUES ('update_member_status', '会员状态已更新', NEW.member_id,
      jsonb_build_object(
        'old_status', 'new',
        'new_status', 'old',
        'check_in_id', NEW.id
      )
    );
  END IF;
  
  RETURN NEW;
END;
$$;


ALTER FUNCTION public.update_member_status() OWNER TO postgres;

--
-- Name: validate_check_in(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.validate_check_in() RETURNS trigger
    LANGUAGE plpgsql
    AS $$ DECLARE v_member RECORD; v_card RECORD; v_daily_check_ins integer; v_has_same_class_check_in boolean; v_is_private boolean; BEGIN IF NOT check_member_exists(NEW.member_id) THEN RAISE EXCEPTION '会员不存在'; END IF; SELECT * INTO v_member FROM members WHERE id = NEW.member_id; v_is_private := (NEW.class_type = 'private'); PERFORM log_debug('validate_check_in', '开始签到验证', jsonb_build_object('member_id', NEW.member_id, 'class_type', NEW.class_type, 'check_in_date', NEW.check_in_date, 'time_slot', NEW.time_slot, 'is_private', v_is_private)); IF NEW.card_id IS NOT NULL THEN SELECT * INTO v_card FROM membership_cards WHERE id = NEW.card_id; IF NOT FOUND THEN PERFORM log_debug('validate_check_in', '会员卡不存在', jsonb_build_object('card_id', NEW.card_id)); RAISE EXCEPTION '会员卡不存在'; END IF; IF v_card.member_id != NEW.member_id THEN PERFORM log_debug('validate_check_in', '会员卡不属于该会员', jsonb_build_object('card_id', NEW.card_id, 'card_member_id', v_card.member_id, 'check_in_member_id', NEW.member_id)); RAISE EXCEPTION '会员卡不属于该会员'; END IF; IF v_card.valid_until IS NOT NULL AND v_card.valid_until < NEW.check_in_date THEN PERFORM log_debug('validate_check_in', '会员卡已过期', jsonb_build_object('card_id', NEW.card_id, 'valid_until', v_card.valid_until, 'check_in_date', NEW.check_in_date)); NEW.is_extra := true; END IF; IF (v_card.card_type = '团课' AND v_is_private) OR (v_card.card_type = '私教课' AND NOT v_is_private) THEN PERFORM log_debug('validate_check_in', '卡类型与课程类型不匹配', jsonb_build_object('card_id', NEW.card_id, 'card_type', v_card.card_type, 'class_type', NEW.class_type, 'is_private', v_is_private)); NEW.is_extra := true; END IF; IF v_is_private AND v_card.remaining_private_sessions <= 0 THEN PERFORM log_debug('validate_check_in', '私教课时不足', jsonb_build_object('card_id', NEW.card_id, 'remaining_sessions', v_card.remaining_private_sessions)); NEW.is_extra := true; ELSIF NOT v_is_private AND v_card.remaining_group_sessions <= 0 THEN PERFORM log_debug('validate_check_in', '团课课时不足', jsonb_build_object('card_id', NEW.card_id, 'remaining_sessions', v_card.remaining_group_sessions)); NEW.is_extra := true; END IF; ELSE PERFORM log_debug('validate_check_in', '未指定会员卡', jsonb_build_object('member_id', NEW.member_id, 'class_type', NEW.class_type)); NEW.is_extra := true; END IF; PERFORM log_debug('validate_check_in', '签到验证完成', jsonb_build_object('member_id', NEW.member_id, 'card_id', NEW.card_id, 'class_type', NEW.class_type, 'is_extra', NEW.is_extra, 'validation_result', CASE WHEN NEW.is_extra THEN '额外签到' ELSE '正常签到' END)); RETURN NEW; END; $$;


ALTER FUNCTION public.validate_check_in() OWNER TO postgres;

--
-- Name: validate_check_in_card(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.validate_check_in_card() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
DECLARE
  v_card RECORD;
BEGIN
  -- 如果没有指定会员卡，则为额外签到
  IF NEW.card_id IS NULL THEN
    NEW.is_extra := true;
    RETURN NEW;
  END IF;

  -- 获取会员卡信息
  SELECT * INTO v_card FROM membership_cards WHERE id = NEW.card_id;
  
  -- 检查会员卡是否存在
  IF NOT FOUND THEN
    NEW.is_extra := true;
    INSERT INTO debug_logs (function_name, message, details)
    VALUES ('validate_check_in_card', '会员卡不存在',
      jsonb_build_object('card_id', NEW.card_id)
    );
    RETURN NEW;
  END IF;

  -- 检查会员卡是否属于该会员
  IF v_card.member_id != NEW.member_id THEN
    NEW.is_extra := true;
    INSERT INTO debug_logs (function_name, message, details)
    VALUES ('validate_check_in_card', '会员卡不属于该会员',
      jsonb_build_object(
        'card_id', NEW.card_id,
        'card_member_id', v_card.member_id,
        'check_in_member_id', NEW.member_id
      )
    );
    RETURN NEW;
  END IF;

  -- 使用CASE表达式简化条件判断
  NEW.is_extra := CASE
    -- 卡类型不匹配
    WHEN (v_card.card_type = '团课' AND NEW.class_type::TEXT = 'private') OR
         (v_card.card_type = '私教课' AND NEW.class_type::TEXT != 'private') THEN true
    -- 卡已过期
    WHEN v_card.valid_until IS NOT NULL AND v_card.valid_until < NEW.check_in_date THEN true
    -- 团课课时卡课时不足
    WHEN v_card.card_type = '团课' AND v_card.card_category = '课时卡' AND
         (v_card.remaining_group_sessions IS NULL OR v_card.remaining_group_sessions <= 0) THEN true
    -- 私教课时不足
    WHEN v_card.card_type = '私教课' AND
         (v_card.remaining_private_sessions IS NULL OR v_card.remaining_private_sessions <= 0) THEN true
    -- 月卡超出每日限制
    WHEN v_card.card_type = '团课' AND v_card.card_category = '月卡' THEN
      CASE
        WHEN v_card.card_subtype = '单次月卡' AND
             (SELECT COUNT(*) FROM check_ins
              WHERE member_id = NEW.member_id
              AND check_in_date = NEW.check_in_date
              AND id IS DISTINCT FROM NEW.id
              AND NOT is_extra) >= 1 THEN true
        WHEN v_card.card_subtype = '双次月卡' AND
             (SELECT COUNT(*) FROM check_ins
              WHERE member_id = NEW.member_id
              AND check_in_date = NEW.check_in_date
              AND id IS DISTINCT FROM NEW.id
              AND NOT is_extra) >= 2 THEN true
        ELSE false
      END
    -- 其他情况为正常签到
    ELSE false
  END;
  
  RETURN NEW;
END;
$$;


ALTER FUNCTION public.validate_check_in_card() OWNER TO postgres;

--
-- Name: validate_member_name(text, text); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.validate_member_name(p_name text, p_email text DEFAULT NULL::text) RETURNS boolean
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $_$
BEGIN
  -- Basic validation
  IF TRIM(p_name) = '' THEN
    RAISE EXCEPTION '姓名不能为空。Name cannot be empty.'
      USING HINT = 'empty_name';
  END IF;

  -- Check for invalid characters
  IF p_name !~ '^[a-zA-Z0-9\u4e00-\u9fa5@._\-\s]+$' THEN
    RAISE EXCEPTION '姓名包含无效字符。Name contains invalid characters.'
      USING HINT = 'invalid_characters';
  END IF;

  RETURN true;
EXCEPTION
  WHEN OTHERS THEN
    RAISE;
END;
$_$;


ALTER FUNCTION public.validate_member_name(p_name text, p_email text) OWNER TO postgres;

--
-- Name: validate_membership_card(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.validate_membership_card() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  -- 如果是新卡或更改了卡类型
  IF TG_OP = 'INSERT' OR OLD.card_type != NEW.card_type THEN
    -- 检查是否已有有效卡
    IF NOT check_valid_cards(NEW.member_id, NEW.card_type, NEW.id) THEN
      RAISE EXCEPTION '会员已有有效的%类型会员卡', NEW.card_type;
    END IF;
  END IF;

  RETURN NEW;
END;
$$;


ALTER FUNCTION public.validate_membership_card() OWNER TO postgres;

--
-- Name: validate_private_time_slot(text, date); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.validate_private_time_slot(p_time_slot text, p_check_in_date date) RETURNS boolean
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $_$
DECLARE
  v_day_of_week integer;
BEGIN
  -- Get day of week (1-7, where 1 is Monday)
  v_day_of_week := EXTRACT(DOW FROM p_check_in_date);
  IF v_day_of_week = 0 THEN
    v_day_of_week := 7;
  END IF;

  -- Validate time slot format (HH:MM-HH:MM)
  IF p_time_slot !~ '^\d{2}:\d{2}-\d{2}:\d{2}$' THEN
    RETURN false;
  END IF;

  -- For weekdays (Monday to Friday)
  IF v_day_of_week BETWEEN 1 AND 5 THEN
    RETURN p_time_slot IN (
      '07:00-08:00', '08:00-09:00', '10:30-11:30',
      '14:00-15:00', '15:00-16:00', '16:00-17:00',
      '18:30-19:30'
    );
  -- For Saturday
  ELSIF v_day_of_week = 6 THEN
    RETURN p_time_slot IN (
      '07:00-08:00', '08:00-09:00', '10:30-11:30',
      '14:00-15:00', '15:00-16:00', '16:00-17:00',
      '18:30-19:30'
    );
  END IF;

  RETURN false;
END;
$_$;


ALTER FUNCTION public.validate_private_time_slot(p_time_slot text, p_check_in_date date) OWNER TO postgres;

--
-- Name: validate_time_slot(text, date, boolean); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.validate_time_slot(p_time_slot text, p_check_in_date date, p_is_private boolean) RETURNS boolean
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $_$
BEGIN
  -- Basic format validation
  IF p_time_slot !~ '^\d{2}:\d{2}-\d{2}:\d{2}$' THEN
    RETURN false;
  END IF;

  -- For group classes
  IF NOT p_is_private THEN
    RETURN p_time_slot IN ('09:00-10:30', '17:00-18:30');
  END IF;

  -- For private classes, trust the frontend validation
  RETURN true;
END;
$_$;


ALTER FUNCTION public.validate_time_slot(p_time_slot text, p_check_in_date date, p_is_private boolean) OWNER TO postgres;

--
-- Name: apply_rls(jsonb, integer); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.apply_rls(wal jsonb, max_record_bytes integer DEFAULT (1024 * 1024)) RETURNS SETOF realtime.wal_rls
    LANGUAGE plpgsql
    AS $$
declare
-- Regclass of the table e.g. public.notes
entity_ regclass = (quote_ident(wal ->> 'schema') || '.' || quote_ident(wal ->> 'table'))::regclass;

-- I, U, D, T: insert, update ...
action realtime.action = (
    case wal ->> 'action'
        when 'I' then 'INSERT'
        when 'U' then 'UPDATE'
        when 'D' then 'DELETE'
        else 'ERROR'
    end
);

-- Is row level security enabled for the table
is_rls_enabled bool = relrowsecurity from pg_class where oid = entity_;

subscriptions realtime.subscription[] = array_agg(subs)
    from
        realtime.subscription subs
    where
        subs.entity = entity_;

-- Subscription vars
roles regrole[] = array_agg(distinct us.claims_role::text)
    from
        unnest(subscriptions) us;

working_role regrole;
claimed_role regrole;
claims jsonb;

subscription_id uuid;
subscription_has_access bool;
visible_to_subscription_ids uuid[] = '{}';

-- structured info for wal's columns
columns realtime.wal_column[];
-- previous identity values for update/delete
old_columns realtime.wal_column[];

error_record_exceeds_max_size boolean = octet_length(wal::text) > max_record_bytes;

-- Primary jsonb output for record
output jsonb;

begin
perform set_config('role', null, true);

columns =
    array_agg(
        (
            x->>'name',
            x->>'type',
            x->>'typeoid',
            realtime.cast(
                (x->'value') #>> '{}',
                coalesce(
                    (x->>'typeoid')::regtype, -- null when wal2json version <= 2.4
                    (x->>'type')::regtype
                )
            ),
            (pks ->> 'name') is not null,
            true
        )::realtime.wal_column
    )
    from
        jsonb_array_elements(wal -> 'columns') x
        left join jsonb_array_elements(wal -> 'pk') pks
            on (x ->> 'name') = (pks ->> 'name');

old_columns =
    array_agg(
        (
            x->>'name',
            x->>'type',
            x->>'typeoid',
            realtime.cast(
                (x->'value') #>> '{}',
                coalesce(
                    (x->>'typeoid')::regtype, -- null when wal2json version <= 2.4
                    (x->>'type')::regtype
                )
            ),
            (pks ->> 'name') is not null,
            true
        )::realtime.wal_column
    )
    from
        jsonb_array_elements(wal -> 'identity') x
        left join jsonb_array_elements(wal -> 'pk') pks
            on (x ->> 'name') = (pks ->> 'name');

for working_role in select * from unnest(roles) loop

    -- Update `is_selectable` for columns and old_columns
    columns =
        array_agg(
            (
                c.name,
                c.type_name,
                c.type_oid,
                c.value,
                c.is_pkey,
                pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')
            )::realtime.wal_column
        )
        from
            unnest(columns) c;

    old_columns =
            array_agg(
                (
                    c.name,
                    c.type_name,
                    c.type_oid,
                    c.value,
                    c.is_pkey,
                    pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')
                )::realtime.wal_column
            )
            from
                unnest(old_columns) c;

    if action <> 'DELETE' and count(1) = 0 from unnest(columns) c where c.is_pkey then
        return next (
            jsonb_build_object(
                'schema', wal ->> 'schema',
                'table', wal ->> 'table',
                'type', action
            ),
            is_rls_enabled,
            -- subscriptions is already filtered by entity
            (select array_agg(s.subscription_id) from unnest(subscriptions) as s where claims_role = working_role),
            array['Error 400: Bad Request, no primary key']
        )::realtime.wal_rls;

    -- The claims role does not have SELECT permission to the primary key of entity
    elsif action <> 'DELETE' and sum(c.is_selectable::int) <> count(1) from unnest(columns) c where c.is_pkey then
        return next (
            jsonb_build_object(
                'schema', wal ->> 'schema',
                'table', wal ->> 'table',
                'type', action
            ),
            is_rls_enabled,
            (select array_agg(s.subscription_id) from unnest(subscriptions) as s where claims_role = working_role),
            array['Error 401: Unauthorized']
        )::realtime.wal_rls;

    else
        output = jsonb_build_object(
            'schema', wal ->> 'schema',
            'table', wal ->> 'table',
            'type', action,
            'commit_timestamp', to_char(
                ((wal ->> 'timestamp')::timestamptz at time zone 'utc'),
                'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'
            ),
            'columns', (
                select
                    jsonb_agg(
                        jsonb_build_object(
                            'name', pa.attname,
                            'type', pt.typname
                        )
                        order by pa.attnum asc
                    )
                from
                    pg_attribute pa
                    join pg_type pt
                        on pa.atttypid = pt.oid
                where
                    attrelid = entity_
                    and attnum > 0
                    and pg_catalog.has_column_privilege(working_role, entity_, pa.attname, 'SELECT')
            )
        )
        -- Add "record" key for insert and update
        || case
            when action in ('INSERT', 'UPDATE') then
                jsonb_build_object(
                    'record',
                    (
                        select
                            jsonb_object_agg(
                                -- if unchanged toast, get column name and value from old record
                                coalesce((c).name, (oc).name),
                                case
                                    when (c).name is null then (oc).value
                                    else (c).value
                                end
                            )
                        from
                            unnest(columns) c
                            full outer join unnest(old_columns) oc
                                on (c).name = (oc).name
                        where
                            coalesce((c).is_selectable, (oc).is_selectable)
                            and ( not error_record_exceeds_max_size or (octet_length((c).value::text) <= 64))
                    )
                )
            else '{}'::jsonb
        end
        -- Add "old_record" key for update and delete
        || case
            when action = 'UPDATE' then
                jsonb_build_object(
                        'old_record',
                        (
                            select jsonb_object_agg((c).name, (c).value)
                            from unnest(old_columns) c
                            where
                                (c).is_selectable
                                and ( not error_record_exceeds_max_size or (octet_length((c).value::text) <= 64))
                        )
                    )
            when action = 'DELETE' then
                jsonb_build_object(
                    'old_record',
                    (
                        select jsonb_object_agg((c).name, (c).value)
                        from unnest(old_columns) c
                        where
                            (c).is_selectable
                            and ( not error_record_exceeds_max_size or (octet_length((c).value::text) <= 64))
                            and ( not is_rls_enabled or (c).is_pkey ) -- if RLS enabled, we can't secure deletes so filter to pkey
                    )
                )
            else '{}'::jsonb
        end;

        -- Create the prepared statement
        if is_rls_enabled and action <> 'DELETE' then
            if (select 1 from pg_prepared_statements where name = 'walrus_rls_stmt' limit 1) > 0 then
                deallocate walrus_rls_stmt;
            end if;
            execute realtime.build_prepared_statement_sql('walrus_rls_stmt', entity_, columns);
        end if;

        visible_to_subscription_ids = '{}';

        for subscription_id, claims in (
                select
                    subs.subscription_id,
                    subs.claims
                from
                    unnest(subscriptions) subs
                where
                    subs.entity = entity_
                    and subs.claims_role = working_role
                    and (
                        realtime.is_visible_through_filters(columns, subs.filters)
                        or (
                          action = 'DELETE'
                          and realtime.is_visible_through_filters(old_columns, subs.filters)
                        )
                    )
        ) loop

            if not is_rls_enabled or action = 'DELETE' then
                visible_to_subscription_ids = visible_to_subscription_ids || subscription_id;
            else
                -- Check if RLS allows the role to see the record
                perform
                    -- Trim leading and trailing quotes from working_role because set_config
                    -- doesn't recognize the role as valid if they are included
                    set_config('role', trim(both '"' from working_role::text), true),
                    set_config('request.jwt.claims', claims::text, true);

                execute 'execute walrus_rls_stmt' into subscription_has_access;

                if subscription_has_access then
                    visible_to_subscription_ids = visible_to_subscription_ids || subscription_id;
                end if;
            end if;
        end loop;

        perform set_config('role', null, true);

        return next (
            output,
            is_rls_enabled,
            visible_to_subscription_ids,
            case
                when error_record_exceeds_max_size then array['Error 413: Payload Too Large']
                else '{}'
            end
        )::realtime.wal_rls;

    end if;
end loop;

perform set_config('role', null, true);
end;
$$;


ALTER FUNCTION realtime.apply_rls(wal jsonb, max_record_bytes integer) OWNER TO supabase_admin;

--
-- Name: broadcast_changes(text, text, text, text, text, record, record, text); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.broadcast_changes(topic_name text, event_name text, operation text, table_name text, table_schema text, new record, old record, level text DEFAULT 'ROW'::text) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
    -- Declare a variable to hold the JSONB representation of the row
    row_data jsonb := '{}'::jsonb;
BEGIN
    IF level = 'STATEMENT' THEN
        RAISE EXCEPTION 'function can only be triggered for each row, not for each statement';
    END IF;
    -- Check the operation type and handle accordingly
    IF operation = 'INSERT' OR operation = 'UPDATE' OR operation = 'DELETE' THEN
        row_data := jsonb_build_object('old_record', OLD, 'record', NEW, 'operation', operation, 'table', table_name, 'schema', table_schema);
        PERFORM realtime.send (row_data, event_name, topic_name);
    ELSE
        RAISE EXCEPTION 'Unexpected operation type: %', operation;
    END IF;
EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION 'Failed to process the row: %', SQLERRM;
END;

$$;


ALTER FUNCTION realtime.broadcast_changes(topic_name text, event_name text, operation text, table_name text, table_schema text, new record, old record, level text) OWNER TO supabase_admin;

--
-- Name: build_prepared_statement_sql(text, regclass, realtime.wal_column[]); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]) RETURNS text
    LANGUAGE sql
    AS $$
      /*
      Builds a sql string that, if executed, creates a prepared statement to
      tests retrive a row from *entity* by its primary key columns.
      Example
          select realtime.build_prepared_statement_sql('public.notes', '{"id"}'::text[], '{"bigint"}'::text[])
      */
          select
      'prepare ' || prepared_statement_name || ' as
          select
              exists(
                  select
                      1
                  from
                      ' || entity || '
                  where
                      ' || string_agg(quote_ident(pkc.name) || '=' || quote_nullable(pkc.value #>> '{}') , ' and ') || '
              )'
          from
              unnest(columns) pkc
          where
              pkc.is_pkey
          group by
              entity
      $$;


ALTER FUNCTION realtime.build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]) OWNER TO supabase_admin;

--
-- Name: cast(text, regtype); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime."cast"(val text, type_ regtype) RETURNS jsonb
    LANGUAGE plpgsql IMMUTABLE
    AS $$
    declare
      res jsonb;
    begin
      execute format('select to_jsonb(%L::'|| type_::text || ')', val)  into res;
      return res;
    end
    $$;


ALTER FUNCTION realtime."cast"(val text, type_ regtype) OWNER TO supabase_admin;

--
-- Name: check_equality_op(realtime.equality_op, regtype, text, text); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text) RETURNS boolean
    LANGUAGE plpgsql IMMUTABLE
    AS $$
      /*
      Casts *val_1* and *val_2* as type *type_* and check the *op* condition for truthiness
      */
      declare
          op_symbol text = (
              case
                  when op = 'eq' then '='
                  when op = 'neq' then '!='
                  when op = 'lt' then '<'
                  when op = 'lte' then '<='
                  when op = 'gt' then '>'
                  when op = 'gte' then '>='
                  when op = 'in' then '= any'
                  else 'UNKNOWN OP'
              end
          );
          res boolean;
      begin
          execute format(
              'select %L::'|| type_::text || ' ' || op_symbol
              || ' ( %L::'
              || (
                  case
                      when op = 'in' then type_::text || '[]'
                      else type_::text end
              )
              || ')', val_1, val_2) into res;
          return res;
      end;
      $$;


ALTER FUNCTION realtime.check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text) OWNER TO supabase_admin;

--
-- Name: is_visible_through_filters(realtime.wal_column[], realtime.user_defined_filter[]); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]) RETURNS boolean
    LANGUAGE sql IMMUTABLE
    AS $_$
    /*
    Should the record be visible (true) or filtered out (false) after *filters* are applied
    */
        select
            -- Default to allowed when no filters present
            $2 is null -- no filters. this should not happen because subscriptions has a default
            or array_length($2, 1) is null -- array length of an empty array is null
            or bool_and(
                coalesce(
                    realtime.check_equality_op(
                        op:=f.op,
                        type_:=coalesce(
                            col.type_oid::regtype, -- null when wal2json version <= 2.4
                            col.type_name::regtype
                        ),
                        -- cast jsonb to text
                        val_1:=col.value #>> '{}',
                        val_2:=f.value
                    ),
                    false -- if null, filter does not match
                )
            )
        from
            unnest(filters) f
            join unnest(columns) col
                on f.column_name = col.name;
    $_$;


ALTER FUNCTION realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]) OWNER TO supabase_admin;

--
-- Name: list_changes(name, name, integer, integer); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer) RETURNS SETOF realtime.wal_rls
    LANGUAGE sql
    SET log_min_messages TO 'fatal'
    AS $$
      with pub as (
        select
          concat_ws(
            ',',
            case when bool_or(pubinsert) then 'insert' else null end,
            case when bool_or(pubupdate) then 'update' else null end,
            case when bool_or(pubdelete) then 'delete' else null end
          ) as w2j_actions,
          coalesce(
            string_agg(
              realtime.quote_wal2json(format('%I.%I', schemaname, tablename)::regclass),
              ','
            ) filter (where ppt.tablename is not null and ppt.tablename not like '% %'),
            ''
          ) w2j_add_tables
        from
          pg_publication pp
          left join pg_publication_tables ppt
            on pp.pubname = ppt.pubname
        where
          pp.pubname = publication
        group by
          pp.pubname
        limit 1
      ),
      w2j as (
        select
          x.*, pub.w2j_add_tables
        from
          pub,
          pg_logical_slot_get_changes(
            slot_name, null, max_changes,
            'include-pk', 'true',
            'include-transaction', 'false',
            'include-timestamp', 'true',
            'include-type-oids', 'true',
            'format-version', '2',
            'actions', pub.w2j_actions,
            'add-tables', pub.w2j_add_tables
          ) x
      )
      select
        xyz.wal,
        xyz.is_rls_enabled,
        xyz.subscription_ids,
        xyz.errors
      from
        w2j,
        realtime.apply_rls(
          wal := w2j.data::jsonb,
          max_record_bytes := max_record_bytes
        ) xyz(wal, is_rls_enabled, subscription_ids, errors)
      where
        w2j.w2j_add_tables <> ''
        and xyz.subscription_ids[1] is not null
    $$;


ALTER FUNCTION realtime.list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer) OWNER TO supabase_admin;

--
-- Name: quote_wal2json(regclass); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.quote_wal2json(entity regclass) RETURNS text
    LANGUAGE sql IMMUTABLE STRICT
    AS $$
      select
        (
          select string_agg('' || ch,'')
          from unnest(string_to_array(nsp.nspname::text, null)) with ordinality x(ch, idx)
          where
            not (x.idx = 1 and x.ch = '"')
            and not (
              x.idx = array_length(string_to_array(nsp.nspname::text, null), 1)
              and x.ch = '"'
            )
        )
        || '.'
        || (
          select string_agg('' || ch,'')
          from unnest(string_to_array(pc.relname::text, null)) with ordinality x(ch, idx)
          where
            not (x.idx = 1 and x.ch = '"')
            and not (
              x.idx = array_length(string_to_array(nsp.nspname::text, null), 1)
              and x.ch = '"'
            )
          )
      from
        pg_class pc
        join pg_namespace nsp
          on pc.relnamespace = nsp.oid
      where
        pc.oid = entity
    $$;


ALTER FUNCTION realtime.quote_wal2json(entity regclass) OWNER TO supabase_admin;

--
-- Name: send(jsonb, text, text, boolean); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.send(payload jsonb, event text, topic text, private boolean DEFAULT true) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
  partition_name text;
BEGIN
  partition_name := 'messages_' || to_char(NOW(), 'YYYY_MM_DD');

  IF NOT EXISTS (
    SELECT 1
    FROM pg_class c
    JOIN pg_namespace n ON n.oid = c.relnamespace
    WHERE n.nspname = 'realtime'
    AND c.relname = partition_name
  ) THEN
    EXECUTE format(
      'CREATE TABLE realtime.%I PARTITION OF realtime.messages FOR VALUES FROM (%L) TO (%L)',
      partition_name,
      NOW(),
      (NOW() + interval '1 day')::timestamp
    );
  END IF;

  INSERT INTO realtime.messages (payload, event, topic, private, extension)
  VALUES (payload, event, topic, private, 'broadcast');
END;
$$;


ALTER FUNCTION realtime.send(payload jsonb, event text, topic text, private boolean) OWNER TO supabase_admin;

--
-- Name: subscription_check_filters(); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.subscription_check_filters() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
    /*
    Validates that the user defined filters for a subscription:
    - refer to valid columns that the claimed role may access
    - values are coercable to the correct column type
    */
    declare
        col_names text[] = coalesce(
                array_agg(c.column_name order by c.ordinal_position),
                '{}'::text[]
            )
            from
                information_schema.columns c
            where
                format('%I.%I', c.table_schema, c.table_name)::regclass = new.entity
                and pg_catalog.has_column_privilege(
                    (new.claims ->> 'role'),
                    format('%I.%I', c.table_schema, c.table_name)::regclass,
                    c.column_name,
                    'SELECT'
                );
        filter realtime.user_defined_filter;
        col_type regtype;

        in_val jsonb;
    begin
        for filter in select * from unnest(new.filters) loop
            -- Filtered column is valid
            if not filter.column_name = any(col_names) then
                raise exception 'invalid column for filter %', filter.column_name;
            end if;

            -- Type is sanitized and safe for string interpolation
            col_type = (
                select atttypid::regtype
                from pg_catalog.pg_attribute
                where attrelid = new.entity
                      and attname = filter.column_name
            );
            if col_type is null then
                raise exception 'failed to lookup type for column %', filter.column_name;
            end if;

            -- Set maximum number of entries for in filter
            if filter.op = 'in'::realtime.equality_op then
                in_val = realtime.cast(filter.value, (col_type::text || '[]')::regtype);
                if coalesce(jsonb_array_length(in_val), 0) > 100 then
                    raise exception 'too many values for `in` filter. Maximum 100';
                end if;
            else
                -- raises an exception if value is not coercable to type
                perform realtime.cast(filter.value, col_type);
            end if;

        end loop;

        -- Apply consistent order to filters so the unique constraint on
        -- (subscription_id, entity, filters) can't be tricked by a different filter order
        new.filters = coalesce(
            array_agg(f order by f.column_name, f.op, f.value),
            '{}'
        ) from unnest(new.filters) f;

        return new;
    end;
    $$;


ALTER FUNCTION realtime.subscription_check_filters() OWNER TO supabase_admin;

--
-- Name: to_regrole(text); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.to_regrole(role_name text) RETURNS regrole
    LANGUAGE sql IMMUTABLE
    AS $$ select role_name::regrole $$;


ALTER FUNCTION realtime.to_regrole(role_name text) OWNER TO supabase_admin;

--
-- Name: topic(); Type: FUNCTION; Schema: realtime; Owner: supabase_realtime_admin
--

CREATE FUNCTION realtime.topic() RETURNS text
    LANGUAGE sql STABLE
    AS $$
select nullif(current_setting('realtime.topic', true), '')::text;
$$;


ALTER FUNCTION realtime.topic() OWNER TO supabase_realtime_admin;

--
-- Name: can_insert_object(text, text, uuid, jsonb); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.can_insert_object(bucketid text, name text, owner uuid, metadata jsonb) RETURNS void
    LANGUAGE plpgsql
    AS $$
BEGIN
  INSERT INTO "storage"."objects" ("bucket_id", "name", "owner", "metadata") VALUES (bucketid, name, owner, metadata);
  -- hack to rollback the successful insert
  RAISE sqlstate 'PT200' using
  message = 'ROLLBACK',
  detail = 'rollback successful insert';
END
$$;


ALTER FUNCTION storage.can_insert_object(bucketid text, name text, owner uuid, metadata jsonb) OWNER TO supabase_storage_admin;

--
-- Name: extension(text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.extension(name text) RETURNS text
    LANGUAGE plpgsql
    AS $$
DECLARE
_parts text[];
_filename text;
BEGIN
	select string_to_array(name, '/') into _parts;
	select _parts[array_length(_parts,1)] into _filename;
	-- @todo return the last part instead of 2
	return reverse(split_part(reverse(_filename), '.', 1));
END
$$;


ALTER FUNCTION storage.extension(name text) OWNER TO supabase_storage_admin;

--
-- Name: filename(text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.filename(name text) RETURNS text
    LANGUAGE plpgsql
    AS $$
DECLARE
_parts text[];
BEGIN
	select string_to_array(name, '/') into _parts;
	return _parts[array_length(_parts,1)];
END
$$;


ALTER FUNCTION storage.filename(name text) OWNER TO supabase_storage_admin;

--
-- Name: foldername(text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.foldername(name text) RETURNS text[]
    LANGUAGE plpgsql
    AS $$
DECLARE
_parts text[];
BEGIN
	select string_to_array(name, '/') into _parts;
	return _parts[1:array_length(_parts,1)-1];
END
$$;


ALTER FUNCTION storage.foldername(name text) OWNER TO supabase_storage_admin;

--
-- Name: get_size_by_bucket(); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.get_size_by_bucket() RETURNS TABLE(size bigint, bucket_id text)
    LANGUAGE plpgsql
    AS $$
BEGIN
    return query
        select sum((metadata->>'size')::int) as size, obj.bucket_id
        from "storage".objects as obj
        group by obj.bucket_id;
END
$$;


ALTER FUNCTION storage.get_size_by_bucket() OWNER TO supabase_storage_admin;

--
-- Name: list_multipart_uploads_with_delimiter(text, text, text, integer, text, text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.list_multipart_uploads_with_delimiter(bucket_id text, prefix_param text, delimiter_param text, max_keys integer DEFAULT 100, next_key_token text DEFAULT ''::text, next_upload_token text DEFAULT ''::text) RETURNS TABLE(key text, id text, created_at timestamp with time zone)
    LANGUAGE plpgsql
    AS $_$
BEGIN
    RETURN QUERY EXECUTE
        'SELECT DISTINCT ON(key COLLATE "C") * from (
            SELECT
                CASE
                    WHEN position($2 IN substring(key from length($1) + 1)) > 0 THEN
                        substring(key from 1 for length($1) + position($2 IN substring(key from length($1) + 1)))
                    ELSE
                        key
                END AS key, id, created_at
            FROM
                storage.s3_multipart_uploads
            WHERE
                bucket_id = $5 AND
                key ILIKE $1 || ''%'' AND
                CASE
                    WHEN $4 != '''' AND $6 = '''' THEN
                        CASE
                            WHEN position($2 IN substring(key from length($1) + 1)) > 0 THEN
                                substring(key from 1 for length($1) + position($2 IN substring(key from length($1) + 1))) COLLATE "C" > $4
                            ELSE
                                key COLLATE "C" > $4
                            END
                    ELSE
                        true
                END AND
                CASE
                    WHEN $6 != '''' THEN
                        id COLLATE "C" > $6
                    ELSE
                        true
                    END
            ORDER BY
                key COLLATE "C" ASC, created_at ASC) as e order by key COLLATE "C" LIMIT $3'
        USING prefix_param, delimiter_param, max_keys, next_key_token, bucket_id, next_upload_token;
END;
$_$;


ALTER FUNCTION storage.list_multipart_uploads_with_delimiter(bucket_id text, prefix_param text, delimiter_param text, max_keys integer, next_key_token text, next_upload_token text) OWNER TO supabase_storage_admin;

--
-- Name: list_objects_with_delimiter(text, text, text, integer, text, text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.list_objects_with_delimiter(bucket_id text, prefix_param text, delimiter_param text, max_keys integer DEFAULT 100, start_after text DEFAULT ''::text, next_token text DEFAULT ''::text) RETURNS TABLE(name text, id uuid, metadata jsonb, updated_at timestamp with time zone)
    LANGUAGE plpgsql
    AS $_$
BEGIN
    RETURN QUERY EXECUTE
        'SELECT DISTINCT ON(name COLLATE "C") * from (
            SELECT
                CASE
                    WHEN position($2 IN substring(name from length($1) + 1)) > 0 THEN
                        substring(name from 1 for length($1) + position($2 IN substring(name from length($1) + 1)))
                    ELSE
                        name
                END AS name, id, metadata, updated_at
            FROM
                storage.objects
            WHERE
                bucket_id = $5 AND
                name ILIKE $1 || ''%'' AND
                CASE
                    WHEN $6 != '''' THEN
                    name COLLATE "C" > $6
                ELSE true END
                AND CASE
                    WHEN $4 != '''' THEN
                        CASE
                            WHEN position($2 IN substring(name from length($1) + 1)) > 0 THEN
                                substring(name from 1 for length($1) + position($2 IN substring(name from length($1) + 1))) COLLATE "C" > $4
                            ELSE
                                name COLLATE "C" > $4
                            END
                    ELSE
                        true
                END
            ORDER BY
                name COLLATE "C" ASC) as e order by name COLLATE "C" LIMIT $3'
        USING prefix_param, delimiter_param, max_keys, next_token, bucket_id, start_after;
END;
$_$;


ALTER FUNCTION storage.list_objects_with_delimiter(bucket_id text, prefix_param text, delimiter_param text, max_keys integer, start_after text, next_token text) OWNER TO supabase_storage_admin;

--
-- Name: operation(); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.operation() RETURNS text
    LANGUAGE plpgsql STABLE
    AS $$
BEGIN
    RETURN current_setting('storage.operation', true);
END;
$$;


ALTER FUNCTION storage.operation() OWNER TO supabase_storage_admin;

--
-- Name: search(text, text, integer, integer, integer, text, text, text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.search(prefix text, bucketname text, limits integer DEFAULT 100, levels integer DEFAULT 1, offsets integer DEFAULT 0, search text DEFAULT ''::text, sortcolumn text DEFAULT 'name'::text, sortorder text DEFAULT 'asc'::text) RETURNS TABLE(name text, id uuid, updated_at timestamp with time zone, created_at timestamp with time zone, last_accessed_at timestamp with time zone, metadata jsonb)
    LANGUAGE plpgsql STABLE
    AS $_$
declare
  v_order_by text;
  v_sort_order text;
begin
  case
    when sortcolumn = 'name' then
      v_order_by = 'name';
    when sortcolumn = 'updated_at' then
      v_order_by = 'updated_at';
    when sortcolumn = 'created_at' then
      v_order_by = 'created_at';
    when sortcolumn = 'last_accessed_at' then
      v_order_by = 'last_accessed_at';
    else
      v_order_by = 'name';
  end case;

  case
    when sortorder = 'asc' then
      v_sort_order = 'asc';
    when sortorder = 'desc' then
      v_sort_order = 'desc';
    else
      v_sort_order = 'asc';
  end case;

  v_order_by = v_order_by || ' ' || v_sort_order;

  return query execute
    'with folders as (
       select path_tokens[$1] as folder
       from storage.objects
         where objects.name ilike $2 || $3 || ''%''
           and bucket_id = $4
           and array_length(objects.path_tokens, 1) <> $1
       group by folder
       order by folder ' || v_sort_order || '
     )
     (select folder as "name",
            null as id,
            null as updated_at,
            null as created_at,
            null as last_accessed_at,
            null as metadata from folders)
     union all
     (select path_tokens[$1] as "name",
            id,
            updated_at,
            created_at,
            last_accessed_at,
            metadata
     from storage.objects
     where objects.name ilike $2 || $3 || ''%''
       and bucket_id = $4
       and array_length(objects.path_tokens, 1) = $1
     order by ' || v_order_by || ')
     limit $5
     offset $6' using levels, prefix, search, bucketname, limits, offsets;
end;
$_$;


ALTER FUNCTION storage.search(prefix text, bucketname text, limits integer, levels integer, offsets integer, search text, sortcolumn text, sortorder text) OWNER TO supabase_storage_admin;

--
-- Name: update_updated_at_column(); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.update_updated_at_column() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW; 
END;
$$;


ALTER FUNCTION storage.update_updated_at_column() OWNER TO supabase_storage_admin;

--
-- Name: http_request(); Type: FUNCTION; Schema: supabase_functions; Owner: supabase_functions_admin
--

CREATE FUNCTION supabase_functions.http_request() RETURNS trigger
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'supabase_functions'
    AS $$
  DECLARE
    request_id bigint;
    payload jsonb;
    url text := TG_ARGV[0]::text;
    method text := TG_ARGV[1]::text;
    headers jsonb DEFAULT '{}'::jsonb;
    params jsonb DEFAULT '{}'::jsonb;
    timeout_ms integer DEFAULT 1000;
  BEGIN
    IF url IS NULL OR url = 'null' THEN
      RAISE EXCEPTION 'url argument is missing';
    END IF;

    IF method IS NULL OR method = 'null' THEN
      RAISE EXCEPTION 'method argument is missing';
    END IF;

    IF TG_ARGV[2] IS NULL OR TG_ARGV[2] = 'null' THEN
      headers = '{"Content-Type": "application/json"}'::jsonb;
    ELSE
      headers = TG_ARGV[2]::jsonb;
    END IF;

    IF TG_ARGV[3] IS NULL OR TG_ARGV[3] = 'null' THEN
      params = '{}'::jsonb;
    ELSE
      params = TG_ARGV[3]::jsonb;
    END IF;

    IF TG_ARGV[4] IS NULL OR TG_ARGV[4] = 'null' THEN
      timeout_ms = 1000;
    ELSE
      timeout_ms = TG_ARGV[4]::integer;
    END IF;

    CASE
      WHEN method = 'GET' THEN
        SELECT http_get INTO request_id FROM net.http_get(
          url,
          params,
          headers,
          timeout_ms
        );
      WHEN method = 'POST' THEN
        payload = jsonb_build_object(
          'old_record', OLD,
          'record', NEW,
          'type', TG_OP,
          'table', TG_TABLE_NAME,
          'schema', TG_TABLE_SCHEMA
        );

        SELECT http_post INTO request_id FROM net.http_post(
          url,
          payload,
          params,
          headers,
          timeout_ms
        );
      ELSE
        RAISE EXCEPTION 'method argument % is invalid', method;
    END CASE;

    INSERT INTO supabase_functions.hooks
      (hook_table_id, hook_name, request_id)
    VALUES
      (TG_RELID, TG_NAME, request_id);

    RETURN NEW;
  END
$$;


ALTER FUNCTION supabase_functions.http_request() OWNER TO supabase_functions_admin;

--
-- Name: secrets_encrypt_secret_secret(); Type: FUNCTION; Schema: vault; Owner: supabase_admin
--

CREATE FUNCTION vault.secrets_encrypt_secret_secret() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
		BEGIN
		        new.secret = CASE WHEN new.secret IS NULL THEN NULL ELSE
			CASE WHEN new.key_id IS NULL THEN NULL ELSE pg_catalog.encode(
			  pgsodium.crypto_aead_det_encrypt(
				pg_catalog.convert_to(new.secret, 'utf8'),
				pg_catalog.convert_to((new.id::text || new.description::text || new.created_at::text || new.updated_at::text)::text, 'utf8'),
				new.key_id::uuid,
				new.nonce
			  ),
				'base64') END END;
		RETURN new;
		END;
		$$;


ALTER FUNCTION vault.secrets_encrypt_secret_secret() OWNER TO supabase_admin;

SET default_tablespace = '';

SET default_table_access_method = heap;

--
-- Name: extensions; Type: TABLE; Schema: _realtime; Owner: supabase_admin
--

CREATE TABLE _realtime.extensions (
    id uuid NOT NULL,
    type text,
    settings jsonb,
    tenant_external_id text,
    inserted_at timestamp(0) without time zone NOT NULL,
    updated_at timestamp(0) without time zone NOT NULL
);


ALTER TABLE _realtime.extensions OWNER TO supabase_admin;

--
-- Name: schema_migrations; Type: TABLE; Schema: _realtime; Owner: supabase_admin
--

CREATE TABLE _realtime.schema_migrations (
    version bigint NOT NULL,
    inserted_at timestamp(0) without time zone
);


ALTER TABLE _realtime.schema_migrations OWNER TO supabase_admin;

--
-- Name: tenants; Type: TABLE; Schema: _realtime; Owner: supabase_admin
--

CREATE TABLE _realtime.tenants (
    id uuid NOT NULL,
    name text,
    external_id text,
    jwt_secret text,
    max_concurrent_users integer DEFAULT 200 NOT NULL,
    inserted_at timestamp(0) without time zone NOT NULL,
    updated_at timestamp(0) without time zone NOT NULL,
    max_events_per_second integer DEFAULT 100 NOT NULL,
    postgres_cdc_default text DEFAULT 'postgres_cdc_rls'::text,
    max_bytes_per_second integer DEFAULT 100000 NOT NULL,
    max_channels_per_client integer DEFAULT 100 NOT NULL,
    max_joins_per_second integer DEFAULT 500 NOT NULL,
    suspend boolean DEFAULT false,
    jwt_jwks jsonb,
    notify_private_alpha boolean DEFAULT false,
    private_only boolean DEFAULT false NOT NULL
);


ALTER TABLE _realtime.tenants OWNER TO supabase_admin;

--
-- Name: audit_log_entries; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.audit_log_entries (
    instance_id uuid,
    id uuid NOT NULL,
    payload json,
    created_at timestamp with time zone,
    ip_address character varying(64) DEFAULT ''::character varying NOT NULL
);


ALTER TABLE auth.audit_log_entries OWNER TO supabase_auth_admin;

--
-- Name: TABLE audit_log_entries; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.audit_log_entries IS 'Auth: Audit trail for user actions.';


--
-- Name: flow_state; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.flow_state (
    id uuid NOT NULL,
    user_id uuid,
    auth_code text NOT NULL,
    code_challenge_method auth.code_challenge_method NOT NULL,
    code_challenge text NOT NULL,
    provider_type text NOT NULL,
    provider_access_token text,
    provider_refresh_token text,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    authentication_method text NOT NULL,
    auth_code_issued_at timestamp with time zone
);


ALTER TABLE auth.flow_state OWNER TO supabase_auth_admin;

--
-- Name: TABLE flow_state; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.flow_state IS 'stores metadata for pkce logins';


--
-- Name: identities; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.identities (
    provider_id text NOT NULL,
    user_id uuid NOT NULL,
    identity_data jsonb NOT NULL,
    provider text NOT NULL,
    last_sign_in_at timestamp with time zone,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    email text GENERATED ALWAYS AS (lower((identity_data ->> 'email'::text))) STORED,
    id uuid DEFAULT gen_random_uuid() NOT NULL
);


ALTER TABLE auth.identities OWNER TO supabase_auth_admin;

--
-- Name: TABLE identities; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.identities IS 'Auth: Stores identities associated to a user.';


--
-- Name: COLUMN identities.email; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON COLUMN auth.identities.email IS 'Auth: Email is a generated column that references the optional email property in the identity_data';


--
-- Name: instances; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.instances (
    id uuid NOT NULL,
    uuid uuid,
    raw_base_config text,
    created_at timestamp with time zone,
    updated_at timestamp with time zone
);


ALTER TABLE auth.instances OWNER TO supabase_auth_admin;

--
-- Name: TABLE instances; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.instances IS 'Auth: Manages users across multiple sites.';


--
-- Name: mfa_amr_claims; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.mfa_amr_claims (
    session_id uuid NOT NULL,
    created_at timestamp with time zone NOT NULL,
    updated_at timestamp with time zone NOT NULL,
    authentication_method text NOT NULL,
    id uuid NOT NULL
);


ALTER TABLE auth.mfa_amr_claims OWNER TO supabase_auth_admin;

--
-- Name: TABLE mfa_amr_claims; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.mfa_amr_claims IS 'auth: stores authenticator method reference claims for multi factor authentication';


--
-- Name: mfa_challenges; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.mfa_challenges (
    id uuid NOT NULL,
    factor_id uuid NOT NULL,
    created_at timestamp with time zone NOT NULL,
    verified_at timestamp with time zone,
    ip_address inet NOT NULL,
    otp_code text,
    web_authn_session_data jsonb
);


ALTER TABLE auth.mfa_challenges OWNER TO supabase_auth_admin;

--
-- Name: TABLE mfa_challenges; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.mfa_challenges IS 'auth: stores metadata about challenge requests made';


--
-- Name: mfa_factors; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.mfa_factors (
    id uuid NOT NULL,
    user_id uuid NOT NULL,
    friendly_name text,
    factor_type auth.factor_type NOT NULL,
    status auth.factor_status NOT NULL,
    created_at timestamp with time zone NOT NULL,
    updated_at timestamp with time zone NOT NULL,
    secret text,
    phone text,
    last_challenged_at timestamp with time zone,
    web_authn_credential jsonb,
    web_authn_aaguid uuid
);


ALTER TABLE auth.mfa_factors OWNER TO supabase_auth_admin;

--
-- Name: TABLE mfa_factors; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.mfa_factors IS 'auth: stores metadata about factors';


--
-- Name: one_time_tokens; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.one_time_tokens (
    id uuid NOT NULL,
    user_id uuid NOT NULL,
    token_type auth.one_time_token_type NOT NULL,
    token_hash text NOT NULL,
    relates_to text NOT NULL,
    created_at timestamp without time zone DEFAULT now() NOT NULL,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    CONSTRAINT one_time_tokens_token_hash_check CHECK ((char_length(token_hash) > 0))
);


ALTER TABLE auth.one_time_tokens OWNER TO supabase_auth_admin;

--
-- Name: refresh_tokens; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.refresh_tokens (
    instance_id uuid,
    id bigint NOT NULL,
    token character varying(255),
    user_id character varying(255),
    revoked boolean,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    parent character varying(255),
    session_id uuid
);


ALTER TABLE auth.refresh_tokens OWNER TO supabase_auth_admin;

--
-- Name: TABLE refresh_tokens; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.refresh_tokens IS 'Auth: Store of tokens used to refresh JWT tokens once they expire.';


--
-- Name: refresh_tokens_id_seq; Type: SEQUENCE; Schema: auth; Owner: supabase_auth_admin
--

CREATE SEQUENCE auth.refresh_tokens_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE auth.refresh_tokens_id_seq OWNER TO supabase_auth_admin;

--
-- Name: refresh_tokens_id_seq; Type: SEQUENCE OWNED BY; Schema: auth; Owner: supabase_auth_admin
--

ALTER SEQUENCE auth.refresh_tokens_id_seq OWNED BY auth.refresh_tokens.id;


--
-- Name: saml_providers; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.saml_providers (
    id uuid NOT NULL,
    sso_provider_id uuid NOT NULL,
    entity_id text NOT NULL,
    metadata_xml text NOT NULL,
    metadata_url text,
    attribute_mapping jsonb,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    name_id_format text,
    CONSTRAINT "entity_id not empty" CHECK ((char_length(entity_id) > 0)),
    CONSTRAINT "metadata_url not empty" CHECK (((metadata_url = NULL::text) OR (char_length(metadata_url) > 0))),
    CONSTRAINT "metadata_xml not empty" CHECK ((char_length(metadata_xml) > 0))
);


ALTER TABLE auth.saml_providers OWNER TO supabase_auth_admin;

--
-- Name: TABLE saml_providers; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.saml_providers IS 'Auth: Manages SAML Identity Provider connections.';


--
-- Name: saml_relay_states; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.saml_relay_states (
    id uuid NOT NULL,
    sso_provider_id uuid NOT NULL,
    request_id text NOT NULL,
    for_email text,
    redirect_to text,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    flow_state_id uuid,
    CONSTRAINT "request_id not empty" CHECK ((char_length(request_id) > 0))
);


ALTER TABLE auth.saml_relay_states OWNER TO supabase_auth_admin;

--
-- Name: TABLE saml_relay_states; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.saml_relay_states IS 'Auth: Contains SAML Relay State information for each Service Provider initiated login.';


--
-- Name: schema_migrations; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.schema_migrations (
    version character varying(255) NOT NULL
);


ALTER TABLE auth.schema_migrations OWNER TO supabase_auth_admin;

--
-- Name: TABLE schema_migrations; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.schema_migrations IS 'Auth: Manages updates to the auth system.';


--
-- Name: sessions; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.sessions (
    id uuid NOT NULL,
    user_id uuid NOT NULL,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    factor_id uuid,
    aal auth.aal_level,
    not_after timestamp with time zone,
    refreshed_at timestamp without time zone,
    user_agent text,
    ip inet,
    tag text
);


ALTER TABLE auth.sessions OWNER TO supabase_auth_admin;

--
-- Name: TABLE sessions; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.sessions IS 'Auth: Stores session data associated to a user.';


--
-- Name: COLUMN sessions.not_after; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON COLUMN auth.sessions.not_after IS 'Auth: Not after is a nullable column that contains a timestamp after which the session should be regarded as expired.';


--
-- Name: sso_domains; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.sso_domains (
    id uuid NOT NULL,
    sso_provider_id uuid NOT NULL,
    domain text NOT NULL,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    CONSTRAINT "domain not empty" CHECK ((char_length(domain) > 0))
);


ALTER TABLE auth.sso_domains OWNER TO supabase_auth_admin;

--
-- Name: TABLE sso_domains; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.sso_domains IS 'Auth: Manages SSO email address domain mapping to an SSO Identity Provider.';


--
-- Name: sso_providers; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.sso_providers (
    id uuid NOT NULL,
    resource_id text,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    CONSTRAINT "resource_id not empty" CHECK (((resource_id = NULL::text) OR (char_length(resource_id) > 0)))
);


ALTER TABLE auth.sso_providers OWNER TO supabase_auth_admin;

--
-- Name: TABLE sso_providers; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.sso_providers IS 'Auth: Manages SSO identity provider information; see saml_providers for SAML.';


--
-- Name: COLUMN sso_providers.resource_id; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON COLUMN auth.sso_providers.resource_id IS 'Auth: Uniquely identifies a SSO provider according to a user-chosen resource ID (case insensitive), useful in infrastructure as code.';


--
-- Name: users; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.users (
    instance_id uuid,
    id uuid NOT NULL,
    aud character varying(255),
    role character varying(255),
    email character varying(255),
    encrypted_password character varying(255),
    email_confirmed_at timestamp with time zone,
    invited_at timestamp with time zone,
    confirmation_token character varying(255),
    confirmation_sent_at timestamp with time zone,
    recovery_token character varying(255),
    recovery_sent_at timestamp with time zone,
    email_change_token_new character varying(255),
    email_change character varying(255),
    email_change_sent_at timestamp with time zone,
    last_sign_in_at timestamp with time zone,
    raw_app_meta_data jsonb,
    raw_user_meta_data jsonb,
    is_super_admin boolean,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    phone text DEFAULT NULL::character varying,
    phone_confirmed_at timestamp with time zone,
    phone_change text DEFAULT ''::character varying,
    phone_change_token character varying(255) DEFAULT ''::character varying,
    phone_change_sent_at timestamp with time zone,
    confirmed_at timestamp with time zone GENERATED ALWAYS AS (LEAST(email_confirmed_at, phone_confirmed_at)) STORED,
    email_change_token_current character varying(255) DEFAULT ''::character varying,
    email_change_confirm_status smallint DEFAULT 0,
    banned_until timestamp with time zone,
    reauthentication_token character varying(255) DEFAULT ''::character varying,
    reauthentication_sent_at timestamp with time zone,
    is_sso_user boolean DEFAULT false NOT NULL,
    deleted_at timestamp with time zone,
    is_anonymous boolean DEFAULT false NOT NULL,
    CONSTRAINT users_email_change_confirm_status_check CHECK (((email_change_confirm_status >= 0) AND (email_change_confirm_status <= 2)))
);


ALTER TABLE auth.users OWNER TO supabase_auth_admin;

--
-- Name: TABLE users; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.users IS 'Auth: Stores user login data within a secure schema.';


--
-- Name: COLUMN users.is_sso_user; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON COLUMN auth.users.is_sso_user IS 'Auth: Set this column to true when the account comes from SSO. These accounts can have duplicate emails.';


--
-- Name: check_in_logs; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.check_in_logs (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    check_in_id uuid NOT NULL,
    details jsonb NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.check_in_logs OWNER TO postgres;

--
-- Name: check_ins; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.check_ins (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    member_id uuid,
    check_in_date date DEFAULT CURRENT_DATE NOT NULL,
    created_at timestamp with time zone DEFAULT now(),
    is_extra boolean DEFAULT false,
    trainer_id uuid,
    is_1v2 boolean DEFAULT false,
    class_time time without time zone DEFAULT '09:00:00'::time without time zone NOT NULL,
    card_id uuid,
    is_private boolean DEFAULT false NOT NULL,
    time_slot text NOT NULL,
    class_type public.class_type
);


ALTER TABLE public.check_ins OWNER TO postgres;

--
-- Name: TABLE check_ins; Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON TABLE public.check_ins IS 'Check-in records - Reset for testing on 2024-03-20';


--
-- Name: class_schedule; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.class_schedule (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    day_of_week integer NOT NULL,
    class_type public.class_type NOT NULL,
    start_time time without time zone NOT NULL,
    end_time time without time zone NOT NULL,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now(),
    is_private_class boolean DEFAULT false NOT NULL,
    trainer_type text,
    available_trainers uuid[],
    CONSTRAINT class_schedule_day_of_week_check CHECK (((day_of_week >= 1) AND (day_of_week <= 6))),
    CONSTRAINT class_schedule_trainer_type_check CHECK ((trainer_type = ANY (ARRAY['jr'::text, 'senior'::text])))
);


ALTER TABLE public.class_schedule OWNER TO postgres;

--
-- Name: debug_logs; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.debug_logs (
    id integer NOT NULL,
    "timestamp" timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
    function_name text NOT NULL,
    member_id uuid,
    message text NOT NULL,
    details jsonb
);


ALTER TABLE public.debug_logs OWNER TO postgres;

--
-- Name: debug_logs_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
--

CREATE SEQUENCE public.debug_logs_id_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE public.debug_logs_id_seq OWNER TO postgres;

--
-- Name: debug_logs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
--

ALTER SEQUENCE public.debug_logs_id_seq OWNED BY public.debug_logs.id;


--
-- Name: members; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.members (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    name text NOT NULL,
    email text NOT NULL,
    phone text,
    extra_check_ins integer DEFAULT 0 NOT NULL,
    is_new_member boolean DEFAULT true,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now(),
    daily_check_ins integer DEFAULT 0,
    last_check_in_date date
);


ALTER TABLE public.members OWNER TO postgres;

--
-- Name: TABLE members; Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON TABLE public.members IS 'Updated 2024-03-20: Fixed new member status for test members';


--
-- Name: membership_cards; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.membership_cards (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    member_id uuid,
    card_type text NOT NULL,
    card_category text,
    card_subtype text NOT NULL,
    trainer_type text,
    remaining_group_sessions integer,
    remaining_private_sessions integer,
    valid_until date,
    created_at timestamp with time zone DEFAULT now(),
    CONSTRAINT membership_cards_trainer_type_check CHECK ((trainer_type = ANY (ARRAY['jr'::text, 'senior'::text])))
);


ALTER TABLE public.membership_cards OWNER TO postgres;

--
-- Name: membership_card_view; Type: VIEW; Schema: public; Owner: postgres
--

CREATE VIEW public.membership_card_view AS
 SELECT membership_cards.id,
    membership_cards.member_id,
    membership_cards.card_type,
    membership_cards.card_category,
    membership_cards.card_subtype,
    membership_cards.trainer_type,
    membership_cards.remaining_group_sessions,
    membership_cards.remaining_private_sessions,
    membership_cards.valid_until,
    membership_cards.created_at,
        CASE
            WHEN ((membership_cards.card_type = '团课'::text) AND (membership_cards.card_category = '课时卡'::text) AND (membership_cards.card_subtype = '单次卡'::text)) THEN 'single_class'::text
            WHEN ((membership_cards.card_type = '团课'::text) AND (membership_cards.card_category = '课时卡'::text) AND (membership_cards.card_subtype = '两次卡'::text)) THEN 'two_classes'::text
            WHEN ((membership_cards.card_type = '团课'::text) AND (membership_cards.card_category = '课时卡'::text) AND (membership_cards.card_subtype = '10次卡'::text)) THEN 'ten_classes'::text
            WHEN ((membership_cards.card_type = '团课'::text) AND (membership_cards.card_category = '月卡'::text) AND (membership_cards.card_subtype = '单次月卡'::text)) THEN 'single_monthly'::text
            WHEN ((membership_cards.card_type = '团课'::text) AND (membership_cards.card_category = '月卡'::text) AND (membership_cards.card_subtype = '双次月卡'::text)) THEN 'double_monthly'::text
            WHEN ((membership_cards.card_type = '私教课'::text) AND (membership_cards.card_subtype = '单次卡'::text)) THEN 'single_private'::text
            WHEN ((membership_cards.card_type = '私教课'::text) AND (membership_cards.card_subtype = '10次卡'::text)) THEN 'ten_private'::text
            ELSE membership_cards.card_subtype
        END AS card_subtype_code
   FROM public.membership_cards;


ALTER TABLE public.membership_card_view OWNER TO postgres;

--
-- Name: VIEW membership_card_view; Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON VIEW public.membership_card_view IS '会员卡视图，提供标准化的会员卡信息，包括代码映射';


--
-- Name: migration_logs; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.migration_logs (
    id integer NOT NULL,
    migration_name text NOT NULL,
    description text,
    executed_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.migration_logs OWNER TO postgres;

--
-- Name: migration_logs_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
--

CREATE SEQUENCE public.migration_logs_id_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE public.migration_logs_id_seq OWNER TO postgres;

--
-- Name: migration_logs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
--

ALTER SEQUENCE public.migration_logs_id_seq OWNED BY public.migration_logs.id;


--
-- Name: migrations; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.migrations (
    id integer NOT NULL,
    name character varying(255) NOT NULL,
    applied_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP
);


ALTER TABLE public.migrations OWNER TO postgres;

--
-- Name: migrations_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
--

CREATE SEQUENCE public.migrations_id_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE public.migrations_id_seq OWNER TO postgres;

--
-- Name: migrations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
--

ALTER SEQUENCE public.migrations_id_seq OWNED BY public.migrations.id;


--
-- Name: processed_check_ins; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.processed_check_ins (
    check_in_id uuid NOT NULL,
    process_type text NOT NULL,
    processed_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.processed_check_ins OWNER TO postgres;

--
-- Name: trainers; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.trainers (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    name text NOT NULL,
    type text NOT NULL,
    notes text,
    created_at timestamp with time zone DEFAULT now(),
    CONSTRAINT trainers_type_check CHECK ((type = ANY (ARRAY['jr'::text, 'senior'::text])))
);


ALTER TABLE public.trainers OWNER TO postgres;

--
-- Name: messages; Type: TABLE; Schema: realtime; Owner: supabase_realtime_admin
--

CREATE TABLE realtime.messages (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL
)
PARTITION BY RANGE (inserted_at);


ALTER TABLE realtime.messages OWNER TO supabase_realtime_admin;

--
-- Name: messages_2025_03_09; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2025_03_09 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL
);


ALTER TABLE realtime.messages_2025_03_09 OWNER TO supabase_admin;

--
-- Name: messages_2025_03_10; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2025_03_10 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL
);


ALTER TABLE realtime.messages_2025_03_10 OWNER TO supabase_admin;

--
-- Name: messages_2025_03_11; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2025_03_11 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL
);


ALTER TABLE realtime.messages_2025_03_11 OWNER TO supabase_admin;

--
-- Name: messages_2025_03_12; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2025_03_12 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL
);


ALTER TABLE realtime.messages_2025_03_12 OWNER TO supabase_admin;

--
-- Name: messages_2025_03_13; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2025_03_13 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL
);


ALTER TABLE realtime.messages_2025_03_13 OWNER TO supabase_admin;

--
-- Name: messages_2025_03_14; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2025_03_14 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL
);


ALTER TABLE realtime.messages_2025_03_14 OWNER TO supabase_admin;

--
-- Name: schema_migrations; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.schema_migrations (
    version bigint NOT NULL,
    inserted_at timestamp(0) without time zone
);


ALTER TABLE realtime.schema_migrations OWNER TO supabase_admin;

--
-- Name: subscription; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.subscription (
    id bigint NOT NULL,
    subscription_id uuid NOT NULL,
    entity regclass NOT NULL,
    filters realtime.user_defined_filter[] DEFAULT '{}'::realtime.user_defined_filter[] NOT NULL,
    claims jsonb NOT NULL,
    claims_role regrole GENERATED ALWAYS AS (realtime.to_regrole((claims ->> 'role'::text))) STORED NOT NULL,
    created_at timestamp without time zone DEFAULT timezone('utc'::text, now()) NOT NULL
);


ALTER TABLE realtime.subscription OWNER TO supabase_admin;

--
-- Name: subscription_id_seq; Type: SEQUENCE; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE realtime.subscription ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (
    SEQUENCE NAME realtime.subscription_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1
);


--
-- Name: buckets; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.buckets (
    id text NOT NULL,
    name text NOT NULL,
    owner uuid,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now(),
    public boolean DEFAULT false,
    avif_autodetection boolean DEFAULT false,
    file_size_limit bigint,
    allowed_mime_types text[],
    owner_id text
);


ALTER TABLE storage.buckets OWNER TO supabase_storage_admin;

--
-- Name: COLUMN buckets.owner; Type: COMMENT; Schema: storage; Owner: supabase_storage_admin
--

COMMENT ON COLUMN storage.buckets.owner IS 'Field is deprecated, use owner_id instead';


--
-- Name: migrations; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.migrations (
    id integer NOT NULL,
    name character varying(100) NOT NULL,
    hash character varying(40) NOT NULL,
    executed_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP
);


ALTER TABLE storage.migrations OWNER TO supabase_storage_admin;

--
-- Name: objects; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.objects (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    bucket_id text,
    name text,
    owner uuid,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now(),
    last_accessed_at timestamp with time zone DEFAULT now(),
    metadata jsonb,
    path_tokens text[] GENERATED ALWAYS AS (string_to_array(name, '/'::text)) STORED,
    version text,
    owner_id text,
    user_metadata jsonb
);


ALTER TABLE storage.objects OWNER TO supabase_storage_admin;

--
-- Name: COLUMN objects.owner; Type: COMMENT; Schema: storage; Owner: supabase_storage_admin
--

COMMENT ON COLUMN storage.objects.owner IS 'Field is deprecated, use owner_id instead';


--
-- Name: s3_multipart_uploads; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.s3_multipart_uploads (
    id text NOT NULL,
    in_progress_size bigint DEFAULT 0 NOT NULL,
    upload_signature text NOT NULL,
    bucket_id text NOT NULL,
    key text NOT NULL COLLATE pg_catalog."C",
    version text NOT NULL,
    owner_id text,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    user_metadata jsonb
);


ALTER TABLE storage.s3_multipart_uploads OWNER TO supabase_storage_admin;

--
-- Name: s3_multipart_uploads_parts; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.s3_multipart_uploads_parts (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    upload_id text NOT NULL,
    size bigint DEFAULT 0 NOT NULL,
    part_number integer NOT NULL,
    bucket_id text NOT NULL,
    key text NOT NULL COLLATE pg_catalog."C",
    etag text NOT NULL,
    owner_id text,
    version text NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE storage.s3_multipart_uploads_parts OWNER TO supabase_storage_admin;

--
-- Name: hooks; Type: TABLE; Schema: supabase_functions; Owner: supabase_functions_admin
--

CREATE TABLE supabase_functions.hooks (
    id bigint NOT NULL,
    hook_table_id integer NOT NULL,
    hook_name text NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    request_id bigint
);


ALTER TABLE supabase_functions.hooks OWNER TO supabase_functions_admin;

--
-- Name: TABLE hooks; Type: COMMENT; Schema: supabase_functions; Owner: supabase_functions_admin
--

COMMENT ON TABLE supabase_functions.hooks IS 'Supabase Functions Hooks: Audit trail for triggered hooks.';


--
-- Name: hooks_id_seq; Type: SEQUENCE; Schema: supabase_functions; Owner: supabase_functions_admin
--

CREATE SEQUENCE supabase_functions.hooks_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE supabase_functions.hooks_id_seq OWNER TO supabase_functions_admin;

--
-- Name: hooks_id_seq; Type: SEQUENCE OWNED BY; Schema: supabase_functions; Owner: supabase_functions_admin
--

ALTER SEQUENCE supabase_functions.hooks_id_seq OWNED BY supabase_functions.hooks.id;


--
-- Name: migrations; Type: TABLE; Schema: supabase_functions; Owner: supabase_functions_admin
--

CREATE TABLE supabase_functions.migrations (
    version text NOT NULL,
    inserted_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE supabase_functions.migrations OWNER TO supabase_functions_admin;

--
-- Name: schema_migrations; Type: TABLE; Schema: supabase_migrations; Owner: postgres
--

CREATE TABLE supabase_migrations.schema_migrations (
    version text NOT NULL,
    statements text[],
    name text
);


ALTER TABLE supabase_migrations.schema_migrations OWNER TO postgres;

--
-- Name: decrypted_secrets; Type: VIEW; Schema: vault; Owner: supabase_admin
--

CREATE VIEW vault.decrypted_secrets AS
 SELECT secrets.id,
    secrets.name,
    secrets.description,
    secrets.secret,
        CASE
            WHEN (secrets.secret IS NULL) THEN NULL::text
            ELSE
            CASE
                WHEN (secrets.key_id IS NULL) THEN NULL::text
                ELSE convert_from(pgsodium.crypto_aead_det_decrypt(decode(secrets.secret, 'base64'::text), convert_to(((((secrets.id)::text || secrets.description) || (secrets.created_at)::text) || (secrets.updated_at)::text), 'utf8'::name), secrets.key_id, secrets.nonce), 'utf8'::name)
            END
        END AS decrypted_secret,
    secrets.key_id,
    secrets.nonce,
    secrets.created_at,
    secrets.updated_at
   FROM vault.secrets;


ALTER TABLE vault.decrypted_secrets OWNER TO supabase_admin;

--
-- Name: messages_2025_03_09; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2025_03_09 FOR VALUES FROM ('2025-03-09 00:00:00') TO ('2025-03-10 00:00:00');


--
-- Name: messages_2025_03_10; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2025_03_10 FOR VALUES FROM ('2025-03-10 00:00:00') TO ('2025-03-11 00:00:00');


--
-- Name: messages_2025_03_11; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2025_03_11 FOR VALUES FROM ('2025-03-11 00:00:00') TO ('2025-03-12 00:00:00');


--
-- Name: messages_2025_03_12; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2025_03_12 FOR VALUES FROM ('2025-03-12 00:00:00') TO ('2025-03-13 00:00:00');


--
-- Name: messages_2025_03_13; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2025_03_13 FOR VALUES FROM ('2025-03-13 00:00:00') TO ('2025-03-14 00:00:00');


--
-- Name: messages_2025_03_14; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2025_03_14 FOR VALUES FROM ('2025-03-14 00:00:00') TO ('2025-03-15 00:00:00');


--
-- Name: refresh_tokens id; Type: DEFAULT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.refresh_tokens ALTER COLUMN id SET DEFAULT nextval('auth.refresh_tokens_id_seq'::regclass);


--
-- Name: debug_logs id; Type: DEFAULT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.debug_logs ALTER COLUMN id SET DEFAULT nextval('public.debug_logs_id_seq'::regclass);


--
-- Name: migration_logs id; Type: DEFAULT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.migration_logs ALTER COLUMN id SET DEFAULT nextval('public.migration_logs_id_seq'::regclass);


--
-- Name: migrations id; Type: DEFAULT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.migrations ALTER COLUMN id SET DEFAULT nextval('public.migrations_id_seq'::regclass);


--
-- Name: hooks id; Type: DEFAULT; Schema: supabase_functions; Owner: supabase_functions_admin
--

ALTER TABLE ONLY supabase_functions.hooks ALTER COLUMN id SET DEFAULT nextval('supabase_functions.hooks_id_seq'::regclass);


--
-- Name: extensions extensions_pkey; Type: CONSTRAINT; Schema: _realtime; Owner: supabase_admin
--

ALTER TABLE ONLY _realtime.extensions
    ADD CONSTRAINT extensions_pkey PRIMARY KEY (id);


--
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: _realtime; Owner: supabase_admin
--

ALTER TABLE ONLY _realtime.schema_migrations
    ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);


--
-- Name: tenants tenants_pkey; Type: CONSTRAINT; Schema: _realtime; Owner: supabase_admin
--

ALTER TABLE ONLY _realtime.tenants
    ADD CONSTRAINT tenants_pkey PRIMARY KEY (id);


--
-- Name: mfa_amr_claims amr_id_pk; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.mfa_amr_claims
    ADD CONSTRAINT amr_id_pk PRIMARY KEY (id);


--
-- Name: audit_log_entries audit_log_entries_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.audit_log_entries
    ADD CONSTRAINT audit_log_entries_pkey PRIMARY KEY (id);


--
-- Name: flow_state flow_state_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.flow_state
    ADD CONSTRAINT flow_state_pkey PRIMARY KEY (id);


--
-- Name: identities identities_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.identities
    ADD CONSTRAINT identities_pkey PRIMARY KEY (id);


--
-- Name: identities identities_provider_id_provider_unique; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.identities
    ADD CONSTRAINT identities_provider_id_provider_unique UNIQUE (provider_id, provider);


--
-- Name: instances instances_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.instances
    ADD CONSTRAINT instances_pkey PRIMARY KEY (id);


--
-- Name: mfa_amr_claims mfa_amr_claims_session_id_authentication_method_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.mfa_amr_claims
    ADD CONSTRAINT mfa_amr_claims_session_id_authentication_method_pkey UNIQUE (session_id, authentication_method);


--
-- Name: mfa_challenges mfa_challenges_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.mfa_challenges
    ADD CONSTRAINT mfa_challenges_pkey PRIMARY KEY (id);


--
-- Name: mfa_factors mfa_factors_last_challenged_at_key; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.mfa_factors
    ADD CONSTRAINT mfa_factors_last_challenged_at_key UNIQUE (last_challenged_at);


--
-- Name: mfa_factors mfa_factors_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.mfa_factors
    ADD CONSTRAINT mfa_factors_pkey PRIMARY KEY (id);


--
-- Name: one_time_tokens one_time_tokens_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.one_time_tokens
    ADD CONSTRAINT one_time_tokens_pkey PRIMARY KEY (id);


--
-- Name: refresh_tokens refresh_tokens_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.refresh_tokens
    ADD CONSTRAINT refresh_tokens_pkey PRIMARY KEY (id);


--
-- Name: refresh_tokens refresh_tokens_token_unique; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.refresh_tokens
    ADD CONSTRAINT refresh_tokens_token_unique UNIQUE (token);


--
-- Name: saml_providers saml_providers_entity_id_key; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.saml_providers
    ADD CONSTRAINT saml_providers_entity_id_key UNIQUE (entity_id);


--
-- Name: saml_providers saml_providers_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.saml_providers
    ADD CONSTRAINT saml_providers_pkey PRIMARY KEY (id);


--
-- Name: saml_relay_states saml_relay_states_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.saml_relay_states
    ADD CONSTRAINT saml_relay_states_pkey PRIMARY KEY (id);


--
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.schema_migrations
    ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);


--
-- Name: sessions sessions_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.sessions
    ADD CONSTRAINT sessions_pkey PRIMARY KEY (id);


--
-- Name: sso_domains sso_domains_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.sso_domains
    ADD CONSTRAINT sso_domains_pkey PRIMARY KEY (id);


--
-- Name: sso_providers sso_providers_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.sso_providers
    ADD CONSTRAINT sso_providers_pkey PRIMARY KEY (id);


--
-- Name: users users_phone_key; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.users
    ADD CONSTRAINT users_phone_key UNIQUE (phone);


--
-- Name: users users_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.users
    ADD CONSTRAINT users_pkey PRIMARY KEY (id);


--
-- Name: check_in_logs check_in_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.check_in_logs
    ADD CONSTRAINT check_in_logs_pkey PRIMARY KEY (id);


--
-- Name: check_ins check_ins_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.check_ins
    ADD CONSTRAINT check_ins_pkey PRIMARY KEY (id);


--
-- Name: class_schedule class_schedule_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.class_schedule
    ADD CONSTRAINT class_schedule_pkey PRIMARY KEY (id);


--
-- Name: debug_logs debug_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.debug_logs
    ADD CONSTRAINT debug_logs_pkey PRIMARY KEY (id);


--
-- Name: members members_email_key; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.members
    ADD CONSTRAINT members_email_key UNIQUE (email);


--
-- Name: members members_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.members
    ADD CONSTRAINT members_pkey PRIMARY KEY (id);


--
-- Name: membership_cards membership_cards_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.membership_cards
    ADD CONSTRAINT membership_cards_pkey PRIMARY KEY (id);


--
-- Name: migration_logs migration_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.migration_logs
    ADD CONSTRAINT migration_logs_pkey PRIMARY KEY (id);


--
-- Name: migrations migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.migrations
    ADD CONSTRAINT migrations_pkey PRIMARY KEY (id);


--
-- Name: trainers trainers_name_unique; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.trainers
    ADD CONSTRAINT trainers_name_unique UNIQUE (name);


--
-- Name: trainers trainers_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.trainers
    ADD CONSTRAINT trainers_pkey PRIMARY KEY (id);


--
-- Name: membership_cards unique_member_card_type; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.membership_cards
    ADD CONSTRAINT unique_member_card_type UNIQUE (member_id, card_type, card_subtype);


--
-- Name: CONSTRAINT unique_member_card_type ON membership_cards; Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON CONSTRAINT unique_member_card_type ON public.membership_cards IS '确保同一会员不能有相同类型和子类型的多张卡';


--
-- Name: members unique_name_email; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.members
    ADD CONSTRAINT unique_name_email UNIQUE (name, email);


--
-- Name: messages messages_pkey; Type: CONSTRAINT; Schema: realtime; Owner: supabase_realtime_admin
--

ALTER TABLE ONLY realtime.messages
    ADD CONSTRAINT messages_pkey PRIMARY KEY (id, inserted_at);


--
-- Name: messages_2025_03_09 messages_2025_03_09_pkey; Type: CONSTRAINT; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages_2025_03_09
    ADD CONSTRAINT messages_2025_03_09_pkey PRIMARY KEY (id, inserted_at);


--
-- Name: messages_2025_03_10 messages_2025_03_10_pkey; Type: CONSTRAINT; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages_2025_03_10
    ADD CONSTRAINT messages_2025_03_10_pkey PRIMARY KEY (id, inserted_at);


--
-- Name: messages_2025_03_11 messages_2025_03_11_pkey; Type: CONSTRAINT; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages_2025_03_11
    ADD CONSTRAINT messages_2025_03_11_pkey PRIMARY KEY (id, inserted_at);


--
-- Name: messages_2025_03_12 messages_2025_03_12_pkey; Type: CONSTRAINT; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages_2025_03_12
    ADD CONSTRAINT messages_2025_03_12_pkey PRIMARY KEY (id, inserted_at);


--
-- Name: messages_2025_03_13 messages_2025_03_13_pkey; Type: CONSTRAINT; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages_2025_03_13
    ADD CONSTRAINT messages_2025_03_13_pkey PRIMARY KEY (id, inserted_at);


--
-- Name: messages_2025_03_14 messages_2025_03_14_pkey; Type: CONSTRAINT; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages_2025_03_14
    ADD CONSTRAINT messages_2025_03_14_pkey PRIMARY KEY (id, inserted_at);


--
-- Name: subscription pk_subscription; Type: CONSTRAINT; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.subscription
    ADD CONSTRAINT pk_subscription PRIMARY KEY (id);


--
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.schema_migrations
    ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);


--
-- Name: buckets buckets_pkey; Type: CONSTRAINT; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE ONLY storage.buckets
    ADD CONSTRAINT buckets_pkey PRIMARY KEY (id);


--
-- Name: migrations migrations_name_key; Type: CONSTRAINT; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE ONLY storage.migrations
    ADD CONSTRAINT migrations_name_key UNIQUE (name);


--
-- Name: migrations migrations_pkey; Type: CONSTRAINT; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE ONLY storage.migrations
    ADD CONSTRAINT migrations_pkey PRIMARY KEY (id);


--
-- Name: objects objects_pkey; Type: CONSTRAINT; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE ONLY storage.objects
    ADD CONSTRAINT objects_pkey PRIMARY KEY (id);


--
-- Name: s3_multipart_uploads_parts s3_multipart_uploads_parts_pkey; Type: CONSTRAINT; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE ONLY storage.s3_multipart_uploads_parts
    ADD CONSTRAINT s3_multipart_uploads_parts_pkey PRIMARY KEY (id);


--
-- Name: s3_multipart_uploads s3_multipart_uploads_pkey; Type: CONSTRAINT; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE ONLY storage.s3_multipart_uploads
    ADD CONSTRAINT s3_multipart_uploads_pkey PRIMARY KEY (id);


--
-- Name: hooks hooks_pkey; Type: CONSTRAINT; Schema: supabase_functions; Owner: supabase_functions_admin
--

ALTER TABLE ONLY supabase_functions.hooks
    ADD CONSTRAINT hooks_pkey PRIMARY KEY (id);


--
-- Name: migrations migrations_pkey; Type: CONSTRAINT; Schema: supabase_functions; Owner: supabase_functions_admin
--

ALTER TABLE ONLY supabase_functions.migrations
    ADD CONSTRAINT migrations_pkey PRIMARY KEY (version);


--
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: supabase_migrations; Owner: postgres
--

ALTER TABLE ONLY supabase_migrations.schema_migrations
    ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);


--
-- Name: extensions_tenant_external_id_index; Type: INDEX; Schema: _realtime; Owner: supabase_admin
--

CREATE INDEX extensions_tenant_external_id_index ON _realtime.extensions USING btree (tenant_external_id);


--
-- Name: extensions_tenant_external_id_type_index; Type: INDEX; Schema: _realtime; Owner: supabase_admin
--

CREATE UNIQUE INDEX extensions_tenant_external_id_type_index ON _realtime.extensions USING btree (tenant_external_id, type);


--
-- Name: tenants_external_id_index; Type: INDEX; Schema: _realtime; Owner: supabase_admin
--

CREATE UNIQUE INDEX tenants_external_id_index ON _realtime.tenants USING btree (external_id);


--
-- Name: audit_logs_instance_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX audit_logs_instance_id_idx ON auth.audit_log_entries USING btree (instance_id);


--
-- Name: confirmation_token_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE UNIQUE INDEX confirmation_token_idx ON auth.users USING btree (confirmation_token) WHERE ((confirmation_token)::text !~ '^[0-9 ]*$'::text);


--
-- Name: email_change_token_current_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE UNIQUE INDEX email_change_token_current_idx ON auth.users USING btree (email_change_token_current) WHERE ((email_change_token_current)::text !~ '^[0-9 ]*$'::text);


--
-- Name: email_change_token_new_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE UNIQUE INDEX email_change_token_new_idx ON auth.users USING btree (email_change_token_new) WHERE ((email_change_token_new)::text !~ '^[0-9 ]*$'::text);


--
-- Name: factor_id_created_at_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX factor_id_created_at_idx ON auth.mfa_factors USING btree (user_id, created_at);


--
-- Name: flow_state_created_at_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX flow_state_created_at_idx ON auth.flow_state USING btree (created_at DESC);


--
-- Name: identities_email_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX identities_email_idx ON auth.identities USING btree (email text_pattern_ops);


--
-- Name: INDEX identities_email_idx; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON INDEX auth.identities_email_idx IS 'Auth: Ensures indexed queries on the email column';


--
-- Name: identities_user_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX identities_user_id_idx ON auth.identities USING btree (user_id);


--
-- Name: idx_auth_code; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX idx_auth_code ON auth.flow_state USING btree (auth_code);


--
-- Name: idx_user_id_auth_method; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX idx_user_id_auth_method ON auth.flow_state USING btree (user_id, authentication_method);


--
-- Name: mfa_challenge_created_at_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX mfa_challenge_created_at_idx ON auth.mfa_challenges USING btree (created_at DESC);


--
-- Name: mfa_factors_user_friendly_name_unique; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE UNIQUE INDEX mfa_factors_user_friendly_name_unique ON auth.mfa_factors USING btree (friendly_name, user_id) WHERE (TRIM(BOTH FROM friendly_name) <> ''::text);


--
-- Name: mfa_factors_user_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX mfa_factors_user_id_idx ON auth.mfa_factors USING btree (user_id);


--
-- Name: one_time_tokens_relates_to_hash_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX one_time_tokens_relates_to_hash_idx ON auth.one_time_tokens USING hash (relates_to);


--
-- Name: one_time_tokens_token_hash_hash_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX one_time_tokens_token_hash_hash_idx ON auth.one_time_tokens USING hash (token_hash);


--
-- Name: one_time_tokens_user_id_token_type_key; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE UNIQUE INDEX one_time_tokens_user_id_token_type_key ON auth.one_time_tokens USING btree (user_id, token_type);


--
-- Name: reauthentication_token_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE UNIQUE INDEX reauthentication_token_idx ON auth.users USING btree (reauthentication_token) WHERE ((reauthentication_token)::text !~ '^[0-9 ]*$'::text);


--
-- Name: recovery_token_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE UNIQUE INDEX recovery_token_idx ON auth.users USING btree (recovery_token) WHERE ((recovery_token)::text !~ '^[0-9 ]*$'::text);


--
-- Name: refresh_tokens_instance_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX refresh_tokens_instance_id_idx ON auth.refresh_tokens USING btree (instance_id);


--
-- Name: refresh_tokens_instance_id_user_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX refresh_tokens_instance_id_user_id_idx ON auth.refresh_tokens USING btree (instance_id, user_id);


--
-- Name: refresh_tokens_parent_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX refresh_tokens_parent_idx ON auth.refresh_tokens USING btree (parent);


--
-- Name: refresh_tokens_session_id_revoked_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX refresh_tokens_session_id_revoked_idx ON auth.refresh_tokens USING btree (session_id, revoked);


--
-- Name: refresh_tokens_updated_at_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX refresh_tokens_updated_at_idx ON auth.refresh_tokens USING btree (updated_at DESC);


--
-- Name: saml_providers_sso_provider_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX saml_providers_sso_provider_id_idx ON auth.saml_providers USING btree (sso_provider_id);


--
-- Name: saml_relay_states_created_at_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX saml_relay_states_created_at_idx ON auth.saml_relay_states USING btree (created_at DESC);


--
-- Name: saml_relay_states_for_email_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX saml_relay_states_for_email_idx ON auth.saml_relay_states USING btree (for_email);


--
-- Name: saml_relay_states_sso_provider_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX saml_relay_states_sso_provider_id_idx ON auth.saml_relay_states USING btree (sso_provider_id);


--
-- Name: sessions_not_after_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX sessions_not_after_idx ON auth.sessions USING btree (not_after DESC);


--
-- Name: sessions_user_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX sessions_user_id_idx ON auth.sessions USING btree (user_id);


--
-- Name: sso_domains_domain_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE UNIQUE INDEX sso_domains_domain_idx ON auth.sso_domains USING btree (lower(domain));


--
-- Name: sso_domains_sso_provider_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX sso_domains_sso_provider_id_idx ON auth.sso_domains USING btree (sso_provider_id);


--
-- Name: sso_providers_resource_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE UNIQUE INDEX sso_providers_resource_id_idx ON auth.sso_providers USING btree (lower(resource_id));


--
-- Name: unique_phone_factor_per_user; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE UNIQUE INDEX unique_phone_factor_per_user ON auth.mfa_factors USING btree (user_id, phone);


--
-- Name: user_id_created_at_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX user_id_created_at_idx ON auth.sessions USING btree (user_id, created_at);


--
-- Name: users_email_partial_key; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE UNIQUE INDEX users_email_partial_key ON auth.users USING btree (email) WHERE (is_sso_user = false);


--
-- Name: INDEX users_email_partial_key; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON INDEX auth.users_email_partial_key IS 'Auth: A partial unique index that applies only when is_sso_user is false';


--
-- Name: users_instance_id_email_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX users_instance_id_email_idx ON auth.users USING btree (instance_id, lower((email)::text));


--
-- Name: users_instance_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX users_instance_id_idx ON auth.users USING btree (instance_id);


--
-- Name: users_is_anonymous_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin
--

CREATE INDEX users_is_anonymous_idx ON auth.users USING btree (is_anonymous);


--
-- Name: check_in_logs_check_in_id_idx; Type: INDEX; Schema: public; Owner: postgres
--

CREATE INDEX check_in_logs_check_in_id_idx ON public.check_in_logs USING btree (check_in_id);


--
-- Name: check_in_logs_created_at_idx; Type: INDEX; Schema: public; Owner: postgres
--

CREATE INDEX check_in_logs_created_at_idx ON public.check_in_logs USING btree (created_at);


--
-- Name: check_ins_check_in_date_idx; Type: INDEX; Schema: public; Owner: postgres
--

CREATE INDEX check_ins_check_in_date_idx ON public.check_ins USING btree (check_in_date);


--
-- Name: check_ins_member_id_idx; Type: INDEX; Schema: public; Owner: postgres
--

CREATE INDEX check_ins_member_id_idx ON public.check_ins USING btree (member_id);


--
-- Name: idx_check_ins_member_date_class; Type: INDEX; Schema: public; Owner: postgres
--

CREATE INDEX idx_check_ins_member_date_class ON public.check_ins USING btree (member_id, check_in_date, class_type);


--
-- Name: idx_members_name_email; Type: INDEX; Schema: public; Owner: postgres
--

CREATE INDEX idx_members_name_email ON public.members USING btree (name, email);


--
-- Name: idx_membership_cards_remaining_sessions; Type: INDEX; Schema: public; Owner: postgres
--

CREATE INDEX idx_membership_cards_remaining_sessions ON public.membership_cards USING btree (card_type, card_category, COALESCE(remaining_group_sessions, 0), COALESCE(remaining_private_sessions, 0));


--
-- Name: idx_membership_cards_types; Type: INDEX; Schema: public; Owner: postgres
--

CREATE INDEX idx_membership_cards_types ON public.membership_cards USING btree (card_type, card_category, card_subtype);


--
-- Name: idx_membership_cards_valid_until; Type: INDEX; Schema: public; Owner: postgres
--

CREATE INDEX idx_membership_cards_valid_until ON public.membership_cards USING btree (valid_until);


--
-- Name: members_email_idx; Type: INDEX; Schema: public; Owner: postgres
--

CREATE INDEX members_email_idx ON public.members USING btree (email);


--
-- Name: members_name_idx; Type: INDEX; Schema: public; Owner: postgres
--

CREATE INDEX members_name_idx ON public.members USING btree (name);


--
-- Name: ix_realtime_subscription_entity; Type: INDEX; Schema: realtime; Owner: supabase_admin
--

CREATE INDEX ix_realtime_subscription_entity ON realtime.subscription USING btree (entity);


--
-- Name: subscription_subscription_id_entity_filters_key; Type: INDEX; Schema: realtime; Owner: supabase_admin
--

CREATE UNIQUE INDEX subscription_subscription_id_entity_filters_key ON realtime.subscription USING btree (subscription_id, entity, filters);


--
-- Name: bname; Type: INDEX; Schema: storage; Owner: supabase_storage_admin
--

CREATE UNIQUE INDEX bname ON storage.buckets USING btree (name);


--
-- Name: bucketid_objname; Type: INDEX; Schema: storage; Owner: supabase_storage_admin
--

CREATE UNIQUE INDEX bucketid_objname ON storage.objects USING btree (bucket_id, name);


--
-- Name: idx_multipart_uploads_list; Type: INDEX; Schema: storage; Owner: supabase_storage_admin
--

CREATE INDEX idx_multipart_uploads_list ON storage.s3_multipart_uploads USING btree (bucket_id, key, created_at);


--
-- Name: idx_objects_bucket_id_name; Type: INDEX; Schema: storage; Owner: supabase_storage_admin
--

CREATE INDEX idx_objects_bucket_id_name ON storage.objects USING btree (bucket_id, name COLLATE "C");


--
-- Name: name_prefix_search; Type: INDEX; Schema: storage; Owner: supabase_storage_admin
--

CREATE INDEX name_prefix_search ON storage.objects USING btree (name text_pattern_ops);


--
-- Name: supabase_functions_hooks_h_table_id_h_name_idx; Type: INDEX; Schema: supabase_functions; Owner: supabase_functions_admin
--

CREATE INDEX supabase_functions_hooks_h_table_id_h_name_idx ON supabase_functions.hooks USING btree (hook_table_id, hook_name);


--
-- Name: supabase_functions_hooks_request_id_idx; Type: INDEX; Schema: supabase_functions; Owner: supabase_functions_admin
--

CREATE INDEX supabase_functions_hooks_request_id_idx ON supabase_functions.hooks USING btree (request_id);


--
-- Name: messages_2025_03_09_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: supabase_realtime_admin
--

ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2025_03_09_pkey;


--
-- Name: messages_2025_03_10_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: supabase_realtime_admin
--

ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2025_03_10_pkey;


--
-- Name: messages_2025_03_11_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: supabase_realtime_admin
--

ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2025_03_11_pkey;


--
-- Name: messages_2025_03_12_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: supabase_realtime_admin
--

ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2025_03_12_pkey;


--
-- Name: messages_2025_03_13_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: supabase_realtime_admin
--

ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2025_03_13_pkey;


--
-- Name: messages_2025_03_14_pkey; Type: INDEX ATTACH; Schema: realtime; Owner: supabase_realtime_admin
--

ALTER INDEX realtime.messages_pkey ATTACH PARTITION realtime.messages_2025_03_14_pkey;


--
-- Name: check_ins check_card_member_match_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER check_card_member_match_trigger BEFORE INSERT OR UPDATE ON public.check_ins FOR EACH ROW EXECUTE FUNCTION public.check_card_member_match();


--
-- Name: membership_cards check_duplicate_cards_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER check_duplicate_cards_trigger BEFORE INSERT OR UPDATE ON public.membership_cards FOR EACH ROW EXECUTE FUNCTION public.check_duplicate_membership_cards();


--
-- Name: check_ins check_in_logging_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER check_in_logging_trigger AFTER INSERT ON public.check_ins FOR EACH ROW EXECUTE FUNCTION public.check_in_logging();


--
-- Name: check_ins check_in_validation_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER check_in_validation_trigger BEFORE INSERT OR UPDATE ON public.check_ins FOR EACH ROW EXECUTE FUNCTION public.validate_check_in();


--
-- Name: check_ins deduct_sessions_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER deduct_sessions_trigger AFTER INSERT ON public.check_ins FOR EACH ROW EXECUTE FUNCTION public.trigger_deduct_sessions();


--
-- Name: check_ins find_valid_card_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER find_valid_card_trigger BEFORE INSERT ON public.check_ins FOR EACH ROW EXECUTE FUNCTION public.find_valid_card_for_checkin();


--
-- Name: membership_cards membership_card_validation_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER membership_card_validation_trigger BEFORE INSERT OR UPDATE ON public.membership_cards FOR EACH ROW EXECUTE FUNCTION public.validate_membership_card();


--
-- Name: check_ins process_check_in_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER process_check_in_trigger AFTER INSERT ON public.check_ins FOR EACH ROW EXECUTE FUNCTION public.process_check_in();


--
-- Name: membership_cards set_card_validity_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER set_card_validity_trigger BEFORE INSERT OR UPDATE OF card_type, card_category, card_subtype ON public.membership_cards FOR EACH ROW EXECUTE FUNCTION public.trigger_set_card_validity();


--
-- Name: check_ins update_check_in_stats_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER update_check_in_stats_trigger AFTER INSERT ON public.check_ins FOR EACH ROW EXECUTE FUNCTION public.update_check_in_stats();


--
-- Name: check_ins update_member_extra_checkins_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER update_member_extra_checkins_trigger AFTER INSERT OR UPDATE OF is_extra ON public.check_ins FOR EACH ROW EXECUTE FUNCTION public.update_member_extra_checkins();


--
-- Name: check_ins update_member_status_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER update_member_status_trigger AFTER INSERT ON public.check_ins FOR EACH ROW EXECUTE FUNCTION public.update_member_status();


--
-- Name: check_ins validate_check_in_trigger; Type: TRIGGER; Schema: public; Owner: postgres
--

CREATE TRIGGER validate_check_in_trigger BEFORE INSERT ON public.check_ins FOR EACH ROW EXECUTE FUNCTION public.validate_check_in();


--
-- Name: subscription tr_check_filters; Type: TRIGGER; Schema: realtime; Owner: supabase_admin
--

CREATE TRIGGER tr_check_filters BEFORE INSERT OR UPDATE ON realtime.subscription FOR EACH ROW EXECUTE FUNCTION realtime.subscription_check_filters();


--
-- Name: objects update_objects_updated_at; Type: TRIGGER; Schema: storage; Owner: supabase_storage_admin
--

CREATE TRIGGER update_objects_updated_at BEFORE UPDATE ON storage.objects FOR EACH ROW EXECUTE FUNCTION storage.update_updated_at_column();


--
-- Name: extensions extensions_tenant_external_id_fkey; Type: FK CONSTRAINT; Schema: _realtime; Owner: supabase_admin
--

ALTER TABLE ONLY _realtime.extensions
    ADD CONSTRAINT extensions_tenant_external_id_fkey FOREIGN KEY (tenant_external_id) REFERENCES _realtime.tenants(external_id) ON DELETE CASCADE;


--
-- Name: identities identities_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.identities
    ADD CONSTRAINT identities_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;


--
-- Name: mfa_amr_claims mfa_amr_claims_session_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.mfa_amr_claims
    ADD CONSTRAINT mfa_amr_claims_session_id_fkey FOREIGN KEY (session_id) REFERENCES auth.sessions(id) ON DELETE CASCADE;


--
-- Name: mfa_challenges mfa_challenges_auth_factor_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.mfa_challenges
    ADD CONSTRAINT mfa_challenges_auth_factor_id_fkey FOREIGN KEY (factor_id) REFERENCES auth.mfa_factors(id) ON DELETE CASCADE;


--
-- Name: mfa_factors mfa_factors_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.mfa_factors
    ADD CONSTRAINT mfa_factors_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;


--
-- Name: one_time_tokens one_time_tokens_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.one_time_tokens
    ADD CONSTRAINT one_time_tokens_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;


--
-- Name: refresh_tokens refresh_tokens_session_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.refresh_tokens
    ADD CONSTRAINT refresh_tokens_session_id_fkey FOREIGN KEY (session_id) REFERENCES auth.sessions(id) ON DELETE CASCADE;


--
-- Name: saml_providers saml_providers_sso_provider_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.saml_providers
    ADD CONSTRAINT saml_providers_sso_provider_id_fkey FOREIGN KEY (sso_provider_id) REFERENCES auth.sso_providers(id) ON DELETE CASCADE;


--
-- Name: saml_relay_states saml_relay_states_flow_state_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.saml_relay_states
    ADD CONSTRAINT saml_relay_states_flow_state_id_fkey FOREIGN KEY (flow_state_id) REFERENCES auth.flow_state(id) ON DELETE CASCADE;


--
-- Name: saml_relay_states saml_relay_states_sso_provider_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.saml_relay_states
    ADD CONSTRAINT saml_relay_states_sso_provider_id_fkey FOREIGN KEY (sso_provider_id) REFERENCES auth.sso_providers(id) ON DELETE CASCADE;


--
-- Name: sessions sessions_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.sessions
    ADD CONSTRAINT sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;


--
-- Name: sso_domains sso_domains_sso_provider_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.sso_domains
    ADD CONSTRAINT sso_domains_sso_provider_id_fkey FOREIGN KEY (sso_provider_id) REFERENCES auth.sso_providers(id) ON DELETE CASCADE;


--
-- Name: check_in_logs check_in_logs_check_in_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.check_in_logs
    ADD CONSTRAINT check_in_logs_check_in_id_fkey FOREIGN KEY (check_in_id) REFERENCES public.check_ins(id) ON DELETE CASCADE;


--
-- Name: check_ins check_ins_card_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.check_ins
    ADD CONSTRAINT check_ins_card_id_fkey FOREIGN KEY (card_id) REFERENCES public.membership_cards(id);


--
-- Name: check_ins check_ins_member_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.check_ins
    ADD CONSTRAINT check_ins_member_id_fkey FOREIGN KEY (member_id) REFERENCES public.members(id);


--
-- Name: check_ins check_ins_trainer_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.check_ins
    ADD CONSTRAINT check_ins_trainer_id_fkey FOREIGN KEY (trainer_id) REFERENCES public.trainers(id);


--
-- Name: membership_cards membership_cards_member_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.membership_cards
    ADD CONSTRAINT membership_cards_member_id_fkey FOREIGN KEY (member_id) REFERENCES public.members(id) ON DELETE CASCADE;


--
-- Name: processed_check_ins processed_check_ins_check_in_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.processed_check_ins
    ADD CONSTRAINT processed_check_ins_check_in_id_fkey FOREIGN KEY (check_in_id) REFERENCES public.check_ins(id);


--
-- Name: objects objects_bucketId_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE ONLY storage.objects
    ADD CONSTRAINT "objects_bucketId_fkey" FOREIGN KEY (bucket_id) REFERENCES storage.buckets(id);


--
-- Name: s3_multipart_uploads s3_multipart_uploads_bucket_id_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE ONLY storage.s3_multipart_uploads
    ADD CONSTRAINT s3_multipart_uploads_bucket_id_fkey FOREIGN KEY (bucket_id) REFERENCES storage.buckets(id);


--
-- Name: s3_multipart_uploads_parts s3_multipart_uploads_parts_bucket_id_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE ONLY storage.s3_multipart_uploads_parts
    ADD CONSTRAINT s3_multipart_uploads_parts_bucket_id_fkey FOREIGN KEY (bucket_id) REFERENCES storage.buckets(id);


--
-- Name: s3_multipart_uploads_parts s3_multipart_uploads_parts_upload_id_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE ONLY storage.s3_multipart_uploads_parts
    ADD CONSTRAINT s3_multipart_uploads_parts_upload_id_fkey FOREIGN KEY (upload_id) REFERENCES storage.s3_multipart_uploads(id) ON DELETE CASCADE;


--
-- Name: audit_log_entries; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.audit_log_entries ENABLE ROW LEVEL SECURITY;

--
-- Name: flow_state; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.flow_state ENABLE ROW LEVEL SECURITY;

--
-- Name: identities; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.identities ENABLE ROW LEVEL SECURITY;

--
-- Name: instances; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.instances ENABLE ROW LEVEL SECURITY;

--
-- Name: mfa_amr_claims; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.mfa_amr_claims ENABLE ROW LEVEL SECURITY;

--
-- Name: mfa_challenges; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.mfa_challenges ENABLE ROW LEVEL SECURITY;

--
-- Name: mfa_factors; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.mfa_factors ENABLE ROW LEVEL SECURITY;

--
-- Name: one_time_tokens; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.one_time_tokens ENABLE ROW LEVEL SECURITY;

--
-- Name: refresh_tokens; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.refresh_tokens ENABLE ROW LEVEL SECURITY;

--
-- Name: saml_providers; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.saml_providers ENABLE ROW LEVEL SECURITY;

--
-- Name: saml_relay_states; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.saml_relay_states ENABLE ROW LEVEL SECURITY;

--
-- Name: schema_migrations; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.schema_migrations ENABLE ROW LEVEL SECURITY;

--
-- Name: sessions; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.sessions ENABLE ROW LEVEL SECURITY;

--
-- Name: sso_domains; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.sso_domains ENABLE ROW LEVEL SECURITY;

--
-- Name: sso_providers; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.sso_providers ENABLE ROW LEVEL SECURITY;

--
-- Name: users; Type: ROW SECURITY; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE auth.users ENABLE ROW LEVEL SECURITY;

--
-- Name: check_ins Admin full access on check_ins; Type: POLICY; Schema: public; Owner: postgres
--

CREATE POLICY "Admin full access on check_ins" ON public.check_ins TO authenticated USING (true) WITH CHECK (true);


--
-- Name: members Admin full access on members; Type: POLICY; Schema: public; Owner: postgres
--

CREATE POLICY "Admin full access on members" ON public.members TO authenticated USING (true) WITH CHECK (true);


--
-- Name: class_schedule Allow admin full access to class schedule; Type: POLICY; Schema: public; Owner: postgres
--

CREATE POLICY "Allow admin full access to class schedule" ON public.class_schedule TO authenticated USING (true);


--
-- Name: check_ins Allow public operations on test check-ins; Type: POLICY; Schema: public; Owner: postgres
--

CREATE POLICY "Allow public operations on test check-ins" ON public.check_ins USING ((member_id IN ( SELECT members.id
   FROM public.members
  WHERE ((members.email ~~ '%.test.mt@example.com'::text) OR (members.email ~~ '%test.checkin%'::text))))) WITH CHECK ((member_id IN ( SELECT members.id
   FROM public.members
  WHERE ((members.email ~~ '%.test.mt@example.com'::text) OR (members.email ~~ '%test.checkin%'::text)))));


--
-- Name: POLICY "Allow public operations on test check-ins" ON check_ins; Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON POLICY "Allow public operations on test check-ins" ON public.check_ins IS 'Allows unauthenticated access to test check-in records for testing purposes';


--
-- Name: members Allow public operations on test members; Type: POLICY; Schema: public; Owner: postgres
--

CREATE POLICY "Allow public operations on test members" ON public.members USING (((email ~~ '%.test.mt@example.com'::text) OR (email ~~ '%test.checkin%'::text))) WITH CHECK (((email ~~ '%.test.mt@example.com'::text) OR (email ~~ '%test.checkin%'::text)));


--
-- Name: POLICY "Allow public operations on test members" ON members; Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON POLICY "Allow public operations on test members" ON public.members IS 'Allows unauthenticated access to test member records for testing purposes';


--
-- Name: class_schedule Allow public read access to class schedule; Type: POLICY; Schema: public; Owner: postgres
--

CREATE POLICY "Allow public read access to class schedule" ON public.class_schedule FOR SELECT USING (true);


--
-- Name: members Allow public read access to members; Type: POLICY; Schema: public; Owner: postgres
--

CREATE POLICY "Allow public read access to members" ON public.members FOR SELECT USING (true);


--
-- Name: check_ins Allow public to create check-ins; Type: POLICY; Schema: public; Owner: postgres
--

CREATE POLICY "Allow public to create check-ins" ON public.check_ins FOR INSERT WITH CHECK (true);


--
-- Name: check_ins Allow public to read check-ins; Type: POLICY; Schema: public; Owner: postgres
--

CREATE POLICY "Allow public to read check-ins" ON public.check_ins FOR SELECT USING (true);


--
-- Name: members Allow public to update members; Type: POLICY; Schema: public; Owner: postgres
--

CREATE POLICY "Allow public to update members" ON public.members USING (true) WITH CHECK (true);


--
-- Name: check_ins; Type: ROW SECURITY; Schema: public; Owner: postgres
--

ALTER TABLE public.check_ins ENABLE ROW LEVEL SECURITY;

--
-- Name: class_schedule; Type: ROW SECURITY; Schema: public; Owner: postgres
--

ALTER TABLE public.class_schedule ENABLE ROW LEVEL SECURITY;

--
-- Name: members; Type: ROW SECURITY; Schema: public; Owner: postgres
--

ALTER TABLE public.members ENABLE ROW LEVEL SECURITY;

--
-- Name: messages; Type: ROW SECURITY; Schema: realtime; Owner: supabase_realtime_admin
--

ALTER TABLE realtime.messages ENABLE ROW LEVEL SECURITY;

--
-- Name: buckets; Type: ROW SECURITY; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE storage.buckets ENABLE ROW LEVEL SECURITY;

--
-- Name: migrations; Type: ROW SECURITY; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE storage.migrations ENABLE ROW LEVEL SECURITY;

--
-- Name: objects; Type: ROW SECURITY; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE storage.objects ENABLE ROW LEVEL SECURITY;

--
-- Name: s3_multipart_uploads; Type: ROW SECURITY; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE storage.s3_multipart_uploads ENABLE ROW LEVEL SECURITY;

--
-- Name: s3_multipart_uploads_parts; Type: ROW SECURITY; Schema: storage; Owner: supabase_storage_admin
--

ALTER TABLE storage.s3_multipart_uploads_parts ENABLE ROW LEVEL SECURITY;

--
-- Name: realtime_messages_publication_; Type: PUBLICATION; Schema: -; Owner: supabase_admin
--

CREATE PUBLICATION realtime_messages_publication_ WITH (publish = 'insert, update, delete, truncate');


ALTER PUBLICATION realtime_messages_publication_ OWNER TO supabase_admin;

--
-- Name: supabase_realtime; Type: PUBLICATION; Schema: -; Owner: postgres
--

CREATE PUBLICATION supabase_realtime WITH (publish = 'insert, update, delete, truncate');


ALTER PUBLICATION supabase_realtime OWNER TO postgres;

--
-- Name: realtime_messages_publication_ messages; Type: PUBLICATION TABLE; Schema: realtime; Owner: supabase_admin
--

ALTER PUBLICATION realtime_messages_publication_ ADD TABLE ONLY realtime.messages;


--
-- Name: SCHEMA auth; Type: ACL; Schema: -; Owner: supabase_admin
--

GRANT USAGE ON SCHEMA auth TO anon;
GRANT USAGE ON SCHEMA auth TO authenticated;
GRANT USAGE ON SCHEMA auth TO service_role;
GRANT ALL ON SCHEMA auth TO supabase_auth_admin;
GRANT ALL ON SCHEMA auth TO dashboard_user;
GRANT ALL ON SCHEMA auth TO postgres;


--
-- Name: SCHEMA cron; Type: ACL; Schema: -; Owner: supabase_admin
--

GRANT USAGE ON SCHEMA cron TO postgres WITH GRANT OPTION;


--
-- Name: SCHEMA extensions; Type: ACL; Schema: -; Owner: postgres
--

GRANT USAGE ON SCHEMA extensions TO anon;
GRANT USAGE ON SCHEMA extensions TO authenticated;
GRANT USAGE ON SCHEMA extensions TO service_role;
GRANT ALL ON SCHEMA extensions TO dashboard_user;


--
-- Name: SCHEMA net; Type: ACL; Schema: -; Owner: supabase_admin
--

GRANT USAGE ON SCHEMA net TO supabase_functions_admin;
GRANT USAGE ON SCHEMA net TO postgres;
GRANT USAGE ON SCHEMA net TO anon;
GRANT USAGE ON SCHEMA net TO authenticated;
GRANT USAGE ON SCHEMA net TO service_role;


--
-- Name: SCHEMA public; Type: ACL; Schema: -; Owner: pg_database_owner
--

GRANT USAGE ON SCHEMA public TO postgres;
GRANT USAGE ON SCHEMA public TO anon;
GRANT USAGE ON SCHEMA public TO authenticated;
GRANT USAGE ON SCHEMA public TO service_role;


--
-- Name: SCHEMA realtime; Type: ACL; Schema: -; Owner: supabase_admin
--

GRANT USAGE ON SCHEMA realtime TO postgres;
GRANT USAGE ON SCHEMA realtime TO anon;
GRANT USAGE ON SCHEMA realtime TO authenticated;
GRANT USAGE ON SCHEMA realtime TO service_role;
GRANT ALL ON SCHEMA realtime TO supabase_realtime_admin;


--
-- Name: SCHEMA storage; Type: ACL; Schema: -; Owner: supabase_admin
--

GRANT ALL ON SCHEMA storage TO postgres;
GRANT USAGE ON SCHEMA storage TO anon;
GRANT USAGE ON SCHEMA storage TO authenticated;
GRANT USAGE ON SCHEMA storage TO service_role;
GRANT ALL ON SCHEMA storage TO supabase_storage_admin;
GRANT ALL ON SCHEMA storage TO dashboard_user;


--
-- Name: SCHEMA supabase_functions; Type: ACL; Schema: -; Owner: supabase_admin
--

GRANT USAGE ON SCHEMA supabase_functions TO postgres;
GRANT USAGE ON SCHEMA supabase_functions TO anon;
GRANT USAGE ON SCHEMA supabase_functions TO authenticated;
GRANT USAGE ON SCHEMA supabase_functions TO service_role;
GRANT ALL ON SCHEMA supabase_functions TO supabase_functions_admin;


--
-- Name: FUNCTION email(); Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT ALL ON FUNCTION auth.email() TO dashboard_user;


--
-- Name: FUNCTION jwt(); Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT ALL ON FUNCTION auth.jwt() TO postgres;
GRANT ALL ON FUNCTION auth.jwt() TO dashboard_user;


--
-- Name: FUNCTION role(); Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT ALL ON FUNCTION auth.role() TO dashboard_user;


--
-- Name: FUNCTION uid(); Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT ALL ON FUNCTION auth.uid() TO dashboard_user;


--
-- Name: FUNCTION alter_job(job_id bigint, schedule text, command text, database text, username text, active boolean); Type: ACL; Schema: cron; Owner: supabase_admin
--

GRANT ALL ON FUNCTION cron.alter_job(job_id bigint, schedule text, command text, database text, username text, active boolean) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION job_cache_invalidate(); Type: ACL; Schema: cron; Owner: supabase_admin
--

GRANT ALL ON FUNCTION cron.job_cache_invalidate() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION schedule(schedule text, command text); Type: ACL; Schema: cron; Owner: supabase_admin
--

GRANT ALL ON FUNCTION cron.schedule(schedule text, command text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION schedule(job_name text, schedule text, command text); Type: ACL; Schema: cron; Owner: supabase_admin
--

GRANT ALL ON FUNCTION cron.schedule(job_name text, schedule text, command text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION schedule_in_database(job_name text, schedule text, command text, database text, username text, active boolean); Type: ACL; Schema: cron; Owner: supabase_admin
--

GRANT ALL ON FUNCTION cron.schedule_in_database(job_name text, schedule text, command text, database text, username text, active boolean) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION unschedule(job_id bigint); Type: ACL; Schema: cron; Owner: supabase_admin
--

GRANT ALL ON FUNCTION cron.unschedule(job_id bigint) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION unschedule(job_name text); Type: ACL; Schema: cron; Owner: supabase_admin
--

GRANT ALL ON FUNCTION cron.unschedule(job_name text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION algorithm_sign(signables text, secret text, algorithm text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.algorithm_sign(signables text, secret text, algorithm text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.algorithm_sign(signables text, secret text, algorithm text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION armor(bytea); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.armor(bytea) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.armor(bytea) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION armor(bytea, text[], text[]); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.armor(bytea, text[], text[]) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.armor(bytea, text[], text[]) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION crypt(text, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.crypt(text, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.crypt(text, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION dearmor(text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.dearmor(text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.dearmor(text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION decrypt(bytea, bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.decrypt(bytea, bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.decrypt(bytea, bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION decrypt_iv(bytea, bytea, bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.decrypt_iv(bytea, bytea, bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.decrypt_iv(bytea, bytea, bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION digest(bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.digest(bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.digest(bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION digest(text, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.digest(text, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.digest(text, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION encrypt(bytea, bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.encrypt(bytea, bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.encrypt(bytea, bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION encrypt_iv(bytea, bytea, bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.encrypt_iv(bytea, bytea, bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.encrypt_iv(bytea, bytea, bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION gen_random_bytes(integer); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.gen_random_bytes(integer) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.gen_random_bytes(integer) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION gen_random_uuid(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.gen_random_uuid() TO dashboard_user;
GRANT ALL ON FUNCTION extensions.gen_random_uuid() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION gen_salt(text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.gen_salt(text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.gen_salt(text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION gen_salt(text, integer); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.gen_salt(text, integer) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.gen_salt(text, integer) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION grant_pg_cron_access(); Type: ACL; Schema: extensions; Owner: postgres
--

REVOKE ALL ON FUNCTION extensions.grant_pg_cron_access() FROM postgres;
GRANT ALL ON FUNCTION extensions.grant_pg_cron_access() TO postgres WITH GRANT OPTION;
GRANT ALL ON FUNCTION extensions.grant_pg_cron_access() TO dashboard_user;


--
-- Name: FUNCTION grant_pg_graphql_access(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.grant_pg_graphql_access() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION grant_pg_net_access(); Type: ACL; Schema: extensions; Owner: postgres
--

REVOKE ALL ON FUNCTION extensions.grant_pg_net_access() FROM postgres;
GRANT ALL ON FUNCTION extensions.grant_pg_net_access() TO postgres WITH GRANT OPTION;
GRANT ALL ON FUNCTION extensions.grant_pg_net_access() TO dashboard_user;


--
-- Name: FUNCTION hmac(bytea, bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.hmac(bytea, bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.hmac(bytea, bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION hmac(text, text, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.hmac(text, text, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.hmac(text, text, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pg_stat_statements(showtext boolean, OUT userid oid, OUT dbid oid, OUT toplevel boolean, OUT queryid bigint, OUT query text, OUT plans bigint, OUT total_plan_time double precision, OUT min_plan_time double precision, OUT max_plan_time double precision, OUT mean_plan_time double precision, OUT stddev_plan_time double precision, OUT calls bigint, OUT total_exec_time double precision, OUT min_exec_time double precision, OUT max_exec_time double precision, OUT mean_exec_time double precision, OUT stddev_exec_time double precision, OUT rows bigint, OUT shared_blks_hit bigint, OUT shared_blks_read bigint, OUT shared_blks_dirtied bigint, OUT shared_blks_written bigint, OUT local_blks_hit bigint, OUT local_blks_read bigint, OUT local_blks_dirtied bigint, OUT local_blks_written bigint, OUT temp_blks_read bigint, OUT temp_blks_written bigint, OUT blk_read_time double precision, OUT blk_write_time double precision, OUT temp_blk_read_time double precision, OUT temp_blk_write_time double precision, OUT wal_records bigint, OUT wal_fpi bigint, OUT wal_bytes numeric, OUT jit_functions bigint, OUT jit_generation_time double precision, OUT jit_inlining_count bigint, OUT jit_inlining_time double precision, OUT jit_optimization_count bigint, OUT jit_optimization_time double precision, OUT jit_emission_count bigint, OUT jit_emission_time double precision); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pg_stat_statements(showtext boolean, OUT userid oid, OUT dbid oid, OUT toplevel boolean, OUT queryid bigint, OUT query text, OUT plans bigint, OUT total_plan_time double precision, OUT min_plan_time double precision, OUT max_plan_time double precision, OUT mean_plan_time double precision, OUT stddev_plan_time double precision, OUT calls bigint, OUT total_exec_time double precision, OUT min_exec_time double precision, OUT max_exec_time double precision, OUT mean_exec_time double precision, OUT stddev_exec_time double precision, OUT rows bigint, OUT shared_blks_hit bigint, OUT shared_blks_read bigint, OUT shared_blks_dirtied bigint, OUT shared_blks_written bigint, OUT local_blks_hit bigint, OUT local_blks_read bigint, OUT local_blks_dirtied bigint, OUT local_blks_written bigint, OUT temp_blks_read bigint, OUT temp_blks_written bigint, OUT blk_read_time double precision, OUT blk_write_time double precision, OUT temp_blk_read_time double precision, OUT temp_blk_write_time double precision, OUT wal_records bigint, OUT wal_fpi bigint, OUT wal_bytes numeric, OUT jit_functions bigint, OUT jit_generation_time double precision, OUT jit_inlining_count bigint, OUT jit_inlining_time double precision, OUT jit_optimization_count bigint, OUT jit_optimization_time double precision, OUT jit_emission_count bigint, OUT jit_emission_time double precision) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pg_stat_statements_info(OUT dealloc bigint, OUT stats_reset timestamp with time zone); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pg_stat_statements_info(OUT dealloc bigint, OUT stats_reset timestamp with time zone) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pg_stat_statements_reset(userid oid, dbid oid, queryid bigint); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pg_stat_statements_reset(userid oid, dbid oid, queryid bigint) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_armor_headers(text, OUT key text, OUT value text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_armor_headers(text, OUT key text, OUT value text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_armor_headers(text, OUT key text, OUT value text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_key_id(bytea); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_key_id(bytea) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_key_id(bytea) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_pub_decrypt(bytea, bytea); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt(bytea, bytea) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt(bytea, bytea) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_pub_decrypt(bytea, bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt(bytea, bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt(bytea, bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_pub_decrypt(bytea, bytea, text, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt(bytea, bytea, text, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt(bytea, bytea, text, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_pub_decrypt_bytea(bytea, bytea); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea, text, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea, text, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_pub_encrypt(text, bytea); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_pub_encrypt(text, bytea) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_pub_encrypt(text, bytea) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_pub_encrypt(text, bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_pub_encrypt(text, bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_pub_encrypt(text, bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_pub_encrypt_bytea(bytea, bytea); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_pub_encrypt_bytea(bytea, bytea) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_pub_encrypt_bytea(bytea, bytea) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_pub_encrypt_bytea(bytea, bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_pub_encrypt_bytea(bytea, bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_pub_encrypt_bytea(bytea, bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_sym_decrypt(bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_sym_decrypt(bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_sym_decrypt(bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_sym_decrypt(bytea, text, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_sym_decrypt(bytea, text, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_sym_decrypt(bytea, text, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_sym_decrypt_bytea(bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_sym_decrypt_bytea(bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_sym_decrypt_bytea(bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_sym_decrypt_bytea(bytea, text, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_sym_decrypt_bytea(bytea, text, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_sym_decrypt_bytea(bytea, text, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_sym_encrypt(text, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_sym_encrypt(text, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_sym_encrypt(text, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_sym_encrypt(text, text, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_sym_encrypt(text, text, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_sym_encrypt(text, text, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_sym_encrypt_bytea(bytea, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_sym_encrypt_bytea(bytea, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_sym_encrypt_bytea(bytea, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgp_sym_encrypt_bytea(bytea, text, text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgp_sym_encrypt_bytea(bytea, text, text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.pgp_sym_encrypt_bytea(bytea, text, text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgrst_ddl_watch(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgrst_ddl_watch() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION pgrst_drop_watch(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.pgrst_drop_watch() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION set_graphql_placeholder(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.set_graphql_placeholder() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION sign(payload json, secret text, algorithm text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.sign(payload json, secret text, algorithm text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.sign(payload json, secret text, algorithm text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION try_cast_double(inp text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.try_cast_double(inp text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.try_cast_double(inp text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION url_decode(data text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.url_decode(data text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.url_decode(data text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION url_encode(data bytea); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.url_encode(data bytea) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.url_encode(data bytea) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION uuid_generate_v1(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.uuid_generate_v1() TO dashboard_user;
GRANT ALL ON FUNCTION extensions.uuid_generate_v1() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION uuid_generate_v1mc(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.uuid_generate_v1mc() TO dashboard_user;
GRANT ALL ON FUNCTION extensions.uuid_generate_v1mc() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION uuid_generate_v3(namespace uuid, name text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.uuid_generate_v3(namespace uuid, name text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.uuid_generate_v3(namespace uuid, name text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION uuid_generate_v4(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.uuid_generate_v4() TO dashboard_user;
GRANT ALL ON FUNCTION extensions.uuid_generate_v4() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION uuid_generate_v5(namespace uuid, name text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.uuid_generate_v5(namespace uuid, name text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.uuid_generate_v5(namespace uuid, name text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION uuid_nil(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.uuid_nil() TO dashboard_user;
GRANT ALL ON FUNCTION extensions.uuid_nil() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION uuid_ns_dns(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.uuid_ns_dns() TO dashboard_user;
GRANT ALL ON FUNCTION extensions.uuid_ns_dns() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION uuid_ns_oid(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.uuid_ns_oid() TO dashboard_user;
GRANT ALL ON FUNCTION extensions.uuid_ns_oid() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION uuid_ns_url(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.uuid_ns_url() TO dashboard_user;
GRANT ALL ON FUNCTION extensions.uuid_ns_url() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION uuid_ns_x500(); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.uuid_ns_x500() TO dashboard_user;
GRANT ALL ON FUNCTION extensions.uuid_ns_x500() TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION verify(token text, secret text, algorithm text); Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON FUNCTION extensions.verify(token text, secret text, algorithm text) TO dashboard_user;
GRANT ALL ON FUNCTION extensions.verify(token text, secret text, algorithm text) TO postgres WITH GRANT OPTION;


--
-- Name: FUNCTION graphql("operationName" text, query text, variables jsonb, extensions jsonb); Type: ACL; Schema: graphql_public; Owner: supabase_admin
--

GRANT ALL ON FUNCTION graphql_public.graphql("operationName" text, query text, variables jsonb, extensions jsonb) TO postgres;
GRANT ALL ON FUNCTION graphql_public.graphql("operationName" text, query text, variables jsonb, extensions jsonb) TO anon;
GRANT ALL ON FUNCTION graphql_public.graphql("operationName" text, query text, variables jsonb, extensions jsonb) TO authenticated;
GRANT ALL ON FUNCTION graphql_public.graphql("operationName" text, query text, variables jsonb, extensions jsonb) TO service_role;


--
-- Name: FUNCTION http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer); Type: ACL; Schema: net; Owner: supabase_admin
--

REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
GRANT ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin;
GRANT ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO postgres;
GRANT ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO anon;
GRANT ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO authenticated;
GRANT ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO service_role;


--
-- Name: FUNCTION http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer); Type: ACL; Schema: net; Owner: supabase_admin
--

REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
GRANT ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin;
GRANT ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO postgres;
GRANT ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO anon;
GRANT ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO authenticated;
GRANT ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO service_role;


--
-- Name: FUNCTION get_auth(p_usename text); Type: ACL; Schema: pgbouncer; Owner: postgres
--

REVOKE ALL ON FUNCTION pgbouncer.get_auth(p_usename text) FROM PUBLIC;
GRANT ALL ON FUNCTION pgbouncer.get_auth(p_usename text) TO pgbouncer;


--
-- Name: FUNCTION crypto_aead_det_decrypt(message bytea, additional bytea, key_uuid uuid, nonce bytea); Type: ACL; Schema: pgsodium; Owner: pgsodium_keymaker
--

GRANT ALL ON FUNCTION pgsodium.crypto_aead_det_decrypt(message bytea, additional bytea, key_uuid uuid, nonce bytea) TO service_role;


--
-- Name: FUNCTION crypto_aead_det_encrypt(message bytea, additional bytea, key_uuid uuid, nonce bytea); Type: ACL; Schema: pgsodium; Owner: pgsodium_keymaker
--

GRANT ALL ON FUNCTION pgsodium.crypto_aead_det_encrypt(message bytea, additional bytea, key_uuid uuid, nonce bytea) TO service_role;


--
-- Name: FUNCTION crypto_aead_det_keygen(); Type: ACL; Schema: pgsodium; Owner: supabase_admin
--

GRANT ALL ON FUNCTION pgsodium.crypto_aead_det_keygen() TO service_role;


--
-- Name: FUNCTION check_card_member_match(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.check_card_member_match() TO anon;
GRANT ALL ON FUNCTION public.check_card_member_match() TO authenticated;
GRANT ALL ON FUNCTION public.check_card_member_match() TO service_role;


--
-- Name: FUNCTION check_card_validity(p_card_id uuid, p_member_id uuid, p_class_type text, p_check_in_date date, p_trainer_id uuid); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.check_card_validity(p_card_id uuid, p_member_id uuid, p_class_type text, p_check_in_date date, p_trainer_id uuid) TO anon;
GRANT ALL ON FUNCTION public.check_card_validity(p_card_id uuid, p_member_id uuid, p_class_type text, p_check_in_date date, p_trainer_id uuid) TO authenticated;
GRANT ALL ON FUNCTION public.check_card_validity(p_card_id uuid, p_member_id uuid, p_class_type text, p_check_in_date date, p_trainer_id uuid) TO service_role;


--
-- Name: FUNCTION check_card_validity_detailed(p_card_id uuid, p_member_id uuid, p_class_type text, p_check_in_date date); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.check_card_validity_detailed(p_card_id uuid, p_member_id uuid, p_class_type text, p_check_in_date date) TO anon;
GRANT ALL ON FUNCTION public.check_card_validity_detailed(p_card_id uuid, p_member_id uuid, p_class_type text, p_check_in_date date) TO authenticated;
GRANT ALL ON FUNCTION public.check_card_validity_detailed(p_card_id uuid, p_member_id uuid, p_class_type text, p_check_in_date date) TO service_role;


--
-- Name: FUNCTION check_duplicate_check_in(p_member_id uuid, p_date date, p_class_type text, p_time_slot text); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.check_duplicate_check_in(p_member_id uuid, p_date date, p_class_type text, p_time_slot text) TO anon;
GRANT ALL ON FUNCTION public.check_duplicate_check_in(p_member_id uuid, p_date date, p_class_type text, p_time_slot text) TO authenticated;
GRANT ALL ON FUNCTION public.check_duplicate_check_in(p_member_id uuid, p_date date, p_class_type text, p_time_slot text) TO service_role;


--
-- Name: FUNCTION check_duplicate_check_in_bool(p_member_id uuid, p_date date, p_class_type text, p_time_slot text); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.check_duplicate_check_in_bool(p_member_id uuid, p_date date, p_class_type text, p_time_slot text) TO anon;
GRANT ALL ON FUNCTION public.check_duplicate_check_in_bool(p_member_id uuid, p_date date, p_class_type text, p_time_slot text) TO authenticated;
GRANT ALL ON FUNCTION public.check_duplicate_check_in_bool(p_member_id uuid, p_date date, p_class_type text, p_time_slot text) TO service_role;


--
-- Name: FUNCTION check_duplicate_membership_cards(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.check_duplicate_membership_cards() TO anon;
GRANT ALL ON FUNCTION public.check_duplicate_membership_cards() TO authenticated;
GRANT ALL ON FUNCTION public.check_duplicate_membership_cards() TO service_role;


--
-- Name: FUNCTION check_in_logging(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.check_in_logging() TO anon;
GRANT ALL ON FUNCTION public.check_in_logging() TO authenticated;
GRANT ALL ON FUNCTION public.check_in_logging() TO service_role;


--
-- Name: FUNCTION check_in_validation(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.check_in_validation() TO anon;
GRANT ALL ON FUNCTION public.check_in_validation() TO authenticated;
GRANT ALL ON FUNCTION public.check_in_validation() TO service_role;


--
-- Name: FUNCTION check_member_exists(p_member_id uuid); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.check_member_exists(p_member_id uuid) TO anon;
GRANT ALL ON FUNCTION public.check_member_exists(p_member_id uuid) TO authenticated;
GRANT ALL ON FUNCTION public.check_member_exists(p_member_id uuid) TO service_role;


--
-- Name: FUNCTION check_monthly_card_daily_limit(p_member_id uuid, p_card_id uuid, p_date date); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.check_monthly_card_daily_limit(p_member_id uuid, p_card_id uuid, p_date date) TO anon;
GRANT ALL ON FUNCTION public.check_monthly_card_daily_limit(p_member_id uuid, p_card_id uuid, p_date date) TO authenticated;
GRANT ALL ON FUNCTION public.check_monthly_card_daily_limit(p_member_id uuid, p_card_id uuid, p_date date) TO service_role;


--
-- Name: FUNCTION check_trainer_level_match(p_card_trainer_type text, p_trainer_type text); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.check_trainer_level_match(p_card_trainer_type text, p_trainer_type text) TO anon;
GRANT ALL ON FUNCTION public.check_trainer_level_match(p_card_trainer_type text, p_trainer_type text) TO authenticated;
GRANT ALL ON FUNCTION public.check_trainer_level_match(p_card_trainer_type text, p_trainer_type text) TO service_role;


--
-- Name: FUNCTION check_valid_cards(p_member_id uuid, p_card_type text, p_current_card_id uuid); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.check_valid_cards(p_member_id uuid, p_card_type text, p_current_card_id uuid) TO anon;
GRANT ALL ON FUNCTION public.check_valid_cards(p_member_id uuid, p_card_type text, p_current_card_id uuid) TO authenticated;
GRANT ALL ON FUNCTION public.check_valid_cards(p_member_id uuid, p_card_type text, p_current_card_id uuid) TO service_role;


--
-- Name: FUNCTION convert_time_slot_to_class_type(p_time_slot text); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.convert_time_slot_to_class_type(p_time_slot text) TO anon;
GRANT ALL ON FUNCTION public.convert_time_slot_to_class_type(p_time_slot text) TO authenticated;
GRANT ALL ON FUNCTION public.convert_time_slot_to_class_type(p_time_slot text) TO service_role;


--
-- Name: FUNCTION create_new_member(p_name text, p_email text, p_class_type public.class_type); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.create_new_member(p_name text, p_email text, p_class_type public.class_type) TO anon;
GRANT ALL ON FUNCTION public.create_new_member(p_name text, p_email text, p_class_type public.class_type) TO authenticated;
GRANT ALL ON FUNCTION public.create_new_member(p_name text, p_email text, p_class_type public.class_type) TO service_role;


--
-- Name: FUNCTION deduct_membership_sessions(p_card_id uuid, p_class_type text, p_is_private boolean, p_is_1v2 boolean); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.deduct_membership_sessions(p_card_id uuid, p_class_type text, p_is_private boolean, p_is_1v2 boolean) TO anon;
GRANT ALL ON FUNCTION public.deduct_membership_sessions(p_card_id uuid, p_class_type text, p_is_private boolean, p_is_1v2 boolean) TO authenticated;
GRANT ALL ON FUNCTION public.deduct_membership_sessions(p_card_id uuid, p_class_type text, p_is_private boolean, p_is_1v2 boolean) TO service_role;


--
-- Name: FUNCTION delete_member(p_member_id uuid); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.delete_member(p_member_id uuid) TO anon;
GRANT ALL ON FUNCTION public.delete_member(p_member_id uuid) TO authenticated;
GRANT ALL ON FUNCTION public.delete_member(p_member_id uuid) TO service_role;


--
-- Name: FUNCTION delete_member_cascade(p_member_id uuid); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.delete_member_cascade(p_member_id uuid) TO anon;
GRANT ALL ON FUNCTION public.delete_member_cascade(p_member_id uuid) TO authenticated;
GRANT ALL ON FUNCTION public.delete_member_cascade(p_member_id uuid) TO service_role;


--
-- Name: FUNCTION find_member_for_checkin(p_name text, p_email text); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.find_member_for_checkin(p_name text, p_email text) TO anon;
GRANT ALL ON FUNCTION public.find_member_for_checkin(p_name text, p_email text) TO authenticated;
GRANT ALL ON FUNCTION public.find_member_for_checkin(p_name text, p_email text) TO service_role;


--
-- Name: FUNCTION find_valid_card_for_checkin(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.find_valid_card_for_checkin() TO anon;
GRANT ALL ON FUNCTION public.find_valid_card_for_checkin() TO authenticated;
GRANT ALL ON FUNCTION public.find_valid_card_for_checkin() TO service_role;


--
-- Name: FUNCTION fix_member_extra_checkins(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.fix_member_extra_checkins() TO anon;
GRANT ALL ON FUNCTION public.fix_member_extra_checkins() TO authenticated;
GRANT ALL ON FUNCTION public.fix_member_extra_checkins() TO service_role;


--
-- Name: FUNCTION generate_mock_check_ins(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.generate_mock_check_ins() TO anon;
GRANT ALL ON FUNCTION public.generate_mock_check_ins() TO authenticated;
GRANT ALL ON FUNCTION public.generate_mock_check_ins() TO service_role;


--
-- Name: FUNCTION get_class_type_from_time_slot(p_time_slot text); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.get_class_type_from_time_slot(p_time_slot text) TO anon;
GRANT ALL ON FUNCTION public.get_class_type_from_time_slot(p_time_slot text) TO authenticated;
GRANT ALL ON FUNCTION public.get_class_type_from_time_slot(p_time_slot text) TO service_role;


--
-- Name: FUNCTION get_valid_time_slot(p_class_type text); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.get_valid_time_slot(p_class_type text) TO anon;
GRANT ALL ON FUNCTION public.get_valid_time_slot(p_class_type text) TO authenticated;
GRANT ALL ON FUNCTION public.get_valid_time_slot(p_class_type text) TO service_role;


--
-- Name: FUNCTION handle_check_in(p_member_id uuid, p_name text, p_email text, p_class_type text, p_check_in_date date, p_card_id uuid, p_trainer_id uuid, p_is_1v2 boolean, p_time_slot text); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.handle_check_in(p_member_id uuid, p_name text, p_email text, p_class_type text, p_check_in_date date, p_card_id uuid, p_trainer_id uuid, p_is_1v2 boolean, p_time_slot text) TO anon;
GRANT ALL ON FUNCTION public.handle_check_in(p_member_id uuid, p_name text, p_email text, p_class_type text, p_check_in_date date, p_card_id uuid, p_trainer_id uuid, p_is_1v2 boolean, p_time_slot text) TO authenticated;
GRANT ALL ON FUNCTION public.handle_check_in(p_member_id uuid, p_name text, p_email text, p_class_type text, p_check_in_date date, p_card_id uuid, p_trainer_id uuid, p_is_1v2 boolean, p_time_slot text) TO service_role;


--
-- Name: FUNCTION init_check_in_session(member_id uuid, class_type_param public.class_type); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.init_check_in_session(member_id uuid, class_type_param public.class_type) TO anon;
GRANT ALL ON FUNCTION public.init_check_in_session(member_id uuid, class_type_param public.class_type) TO authenticated;
GRANT ALL ON FUNCTION public.init_check_in_session(member_id uuid, class_type_param public.class_type) TO service_role;


--
-- Name: FUNCTION log_debug(p_function_name text, p_message text, p_details jsonb, p_member_id uuid); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.log_debug(p_function_name text, p_message text, p_details jsonb, p_member_id uuid) TO anon;
GRANT ALL ON FUNCTION public.log_debug(p_function_name text, p_message text, p_details jsonb, p_member_id uuid) TO authenticated;
GRANT ALL ON FUNCTION public.log_debug(p_function_name text, p_message text, p_details jsonb, p_member_id uuid) TO service_role;


--
-- Name: FUNCTION process_check_in(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.process_check_in() TO anon;
GRANT ALL ON FUNCTION public.process_check_in() TO authenticated;
GRANT ALL ON FUNCTION public.process_check_in() TO service_role;


--
-- Name: FUNCTION register_new_member(p_name text, p_email text, p_time_slot text, p_is_private boolean, p_trainer_id uuid, p_is_1v2 boolean); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.register_new_member(p_name text, p_email text, p_time_slot text, p_is_private boolean, p_trainer_id uuid, p_is_1v2 boolean) TO anon;
GRANT ALL ON FUNCTION public.register_new_member(p_name text, p_email text, p_time_slot text, p_is_private boolean, p_trainer_id uuid, p_is_1v2 boolean) TO authenticated;
GRANT ALL ON FUNCTION public.register_new_member(p_name text, p_email text, p_time_slot text, p_is_private boolean, p_trainer_id uuid, p_is_1v2 boolean) TO service_role;


--
-- Name: FUNCTION search_member(search_term text, exact_match boolean); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.search_member(search_term text, exact_match boolean) TO anon;
GRANT ALL ON FUNCTION public.search_member(search_term text, exact_match boolean) TO authenticated;
GRANT ALL ON FUNCTION public.search_member(search_term text, exact_match boolean) TO service_role;


--
-- Name: FUNCTION set_card_validity(p_card_id uuid, p_card_type text, p_card_category text, p_card_subtype text); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.set_card_validity(p_card_id uuid, p_card_type text, p_card_category text, p_card_subtype text) TO anon;
GRANT ALL ON FUNCTION public.set_card_validity(p_card_id uuid, p_card_type text, p_card_category text, p_card_subtype text) TO authenticated;
GRANT ALL ON FUNCTION public.set_card_validity(p_card_id uuid, p_card_type text, p_card_category text, p_card_subtype text) TO service_role;


--
-- Name: FUNCTION test_expired_card_validation(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.test_expired_card_validation() TO anon;
GRANT ALL ON FUNCTION public.test_expired_card_validation() TO authenticated;
GRANT ALL ON FUNCTION public.test_expired_card_validation() TO service_role;


--
-- Name: FUNCTION test_expired_card_validation_v2(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.test_expired_card_validation_v2() TO anon;
GRANT ALL ON FUNCTION public.test_expired_card_validation_v2() TO authenticated;
GRANT ALL ON FUNCTION public.test_expired_card_validation_v2() TO service_role;


--
-- Name: FUNCTION trigger_deduct_sessions(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.trigger_deduct_sessions() TO anon;
GRANT ALL ON FUNCTION public.trigger_deduct_sessions() TO authenticated;
GRANT ALL ON FUNCTION public.trigger_deduct_sessions() TO service_role;


--
-- Name: FUNCTION trigger_set_card_validity(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.trigger_set_card_validity() TO anon;
GRANT ALL ON FUNCTION public.trigger_set_card_validity() TO authenticated;
GRANT ALL ON FUNCTION public.trigger_set_card_validity() TO service_role;


--
-- Name: FUNCTION update_check_in_stats(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.update_check_in_stats() TO anon;
GRANT ALL ON FUNCTION public.update_check_in_stats() TO authenticated;
GRANT ALL ON FUNCTION public.update_check_in_stats() TO service_role;


--
-- Name: FUNCTION update_member_extra_checkins(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.update_member_extra_checkins() TO anon;
GRANT ALL ON FUNCTION public.update_member_extra_checkins() TO authenticated;
GRANT ALL ON FUNCTION public.update_member_extra_checkins() TO service_role;


--
-- Name: FUNCTION update_member_status(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.update_member_status() TO anon;
GRANT ALL ON FUNCTION public.update_member_status() TO authenticated;
GRANT ALL ON FUNCTION public.update_member_status() TO service_role;


--
-- Name: FUNCTION validate_check_in(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.validate_check_in() TO anon;
GRANT ALL ON FUNCTION public.validate_check_in() TO authenticated;
GRANT ALL ON FUNCTION public.validate_check_in() TO service_role;


--
-- Name: FUNCTION validate_check_in_card(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.validate_check_in_card() TO anon;
GRANT ALL ON FUNCTION public.validate_check_in_card() TO authenticated;
GRANT ALL ON FUNCTION public.validate_check_in_card() TO service_role;


--
-- Name: FUNCTION validate_member_name(p_name text, p_email text); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.validate_member_name(p_name text, p_email text) TO anon;
GRANT ALL ON FUNCTION public.validate_member_name(p_name text, p_email text) TO authenticated;
GRANT ALL ON FUNCTION public.validate_member_name(p_name text, p_email text) TO service_role;


--
-- Name: FUNCTION validate_membership_card(); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.validate_membership_card() TO anon;
GRANT ALL ON FUNCTION public.validate_membership_card() TO authenticated;
GRANT ALL ON FUNCTION public.validate_membership_card() TO service_role;


--
-- Name: FUNCTION validate_private_time_slot(p_time_slot text, p_check_in_date date); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.validate_private_time_slot(p_time_slot text, p_check_in_date date) TO anon;
GRANT ALL ON FUNCTION public.validate_private_time_slot(p_time_slot text, p_check_in_date date) TO authenticated;
GRANT ALL ON FUNCTION public.validate_private_time_slot(p_time_slot text, p_check_in_date date) TO service_role;


--
-- Name: FUNCTION validate_time_slot(p_time_slot text, p_check_in_date date, p_is_private boolean); Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON FUNCTION public.validate_time_slot(p_time_slot text, p_check_in_date date, p_is_private boolean) TO anon;
GRANT ALL ON FUNCTION public.validate_time_slot(p_time_slot text, p_check_in_date date, p_is_private boolean) TO authenticated;
GRANT ALL ON FUNCTION public.validate_time_slot(p_time_slot text, p_check_in_date date, p_is_private boolean) TO service_role;


--
-- Name: FUNCTION apply_rls(wal jsonb, max_record_bytes integer); Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON FUNCTION realtime.apply_rls(wal jsonb, max_record_bytes integer) TO postgres;
GRANT ALL ON FUNCTION realtime.apply_rls(wal jsonb, max_record_bytes integer) TO dashboard_user;
GRANT ALL ON FUNCTION realtime.apply_rls(wal jsonb, max_record_bytes integer) TO anon;
GRANT ALL ON FUNCTION realtime.apply_rls(wal jsonb, max_record_bytes integer) TO authenticated;
GRANT ALL ON FUNCTION realtime.apply_rls(wal jsonb, max_record_bytes integer) TO service_role;
GRANT ALL ON FUNCTION realtime.apply_rls(wal jsonb, max_record_bytes integer) TO supabase_realtime_admin;


--
-- Name: FUNCTION broadcast_changes(topic_name text, event_name text, operation text, table_name text, table_schema text, new record, old record, level text); Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON FUNCTION realtime.broadcast_changes(topic_name text, event_name text, operation text, table_name text, table_schema text, new record, old record, level text) TO postgres;
GRANT ALL ON FUNCTION realtime.broadcast_changes(topic_name text, event_name text, operation text, table_name text, table_schema text, new record, old record, level text) TO dashboard_user;


--
-- Name: FUNCTION build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]); Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON FUNCTION realtime.build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]) TO postgres;
GRANT ALL ON FUNCTION realtime.build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]) TO dashboard_user;
GRANT ALL ON FUNCTION realtime.build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]) TO anon;
GRANT ALL ON FUNCTION realtime.build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]) TO authenticated;
GRANT ALL ON FUNCTION realtime.build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]) TO service_role;
GRANT ALL ON FUNCTION realtime.build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]) TO supabase_realtime_admin;


--
-- Name: FUNCTION "cast"(val text, type_ regtype); Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON FUNCTION realtime."cast"(val text, type_ regtype) TO postgres;
GRANT ALL ON FUNCTION realtime."cast"(val text, type_ regtype) TO dashboard_user;
GRANT ALL ON FUNCTION realtime."cast"(val text, type_ regtype) TO anon;
GRANT ALL ON FUNCTION realtime."cast"(val text, type_ regtype) TO authenticated;
GRANT ALL ON FUNCTION realtime."cast"(val text, type_ regtype) TO service_role;
GRANT ALL ON FUNCTION realtime."cast"(val text, type_ regtype) TO supabase_realtime_admin;


--
-- Name: FUNCTION check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text); Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON FUNCTION realtime.check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text) TO postgres;
GRANT ALL ON FUNCTION realtime.check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text) TO dashboard_user;
GRANT ALL ON FUNCTION realtime.check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text) TO anon;
GRANT ALL ON FUNCTION realtime.check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text) TO authenticated;
GRANT ALL ON FUNCTION realtime.check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text) TO service_role;
GRANT ALL ON FUNCTION realtime.check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text) TO supabase_realtime_admin;


--
-- Name: FUNCTION is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]); Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON FUNCTION realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]) TO postgres;
GRANT ALL ON FUNCTION realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]) TO dashboard_user;
GRANT ALL ON FUNCTION realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]) TO anon;
GRANT ALL ON FUNCTION realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]) TO authenticated;
GRANT ALL ON FUNCTION realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]) TO service_role;
GRANT ALL ON FUNCTION realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]) TO supabase_realtime_admin;


--
-- Name: FUNCTION list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer); Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON FUNCTION realtime.list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer) TO postgres;
GRANT ALL ON FUNCTION realtime.list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer) TO dashboard_user;
GRANT ALL ON FUNCTION realtime.list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer) TO anon;
GRANT ALL ON FUNCTION realtime.list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer) TO authenticated;
GRANT ALL ON FUNCTION realtime.list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer) TO service_role;
GRANT ALL ON FUNCTION realtime.list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer) TO supabase_realtime_admin;


--
-- Name: FUNCTION quote_wal2json(entity regclass); Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON FUNCTION realtime.quote_wal2json(entity regclass) TO postgres;
GRANT ALL ON FUNCTION realtime.quote_wal2json(entity regclass) TO dashboard_user;
GRANT ALL ON FUNCTION realtime.quote_wal2json(entity regclass) TO anon;
GRANT ALL ON FUNCTION realtime.quote_wal2json(entity regclass) TO authenticated;
GRANT ALL ON FUNCTION realtime.quote_wal2json(entity regclass) TO service_role;
GRANT ALL ON FUNCTION realtime.quote_wal2json(entity regclass) TO supabase_realtime_admin;


--
-- Name: FUNCTION send(payload jsonb, event text, topic text, private boolean); Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON FUNCTION realtime.send(payload jsonb, event text, topic text, private boolean) TO postgres;
GRANT ALL ON FUNCTION realtime.send(payload jsonb, event text, topic text, private boolean) TO dashboard_user;


--
-- Name: FUNCTION subscription_check_filters(); Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON FUNCTION realtime.subscription_check_filters() TO postgres;
GRANT ALL ON FUNCTION realtime.subscription_check_filters() TO dashboard_user;
GRANT ALL ON FUNCTION realtime.subscription_check_filters() TO anon;
GRANT ALL ON FUNCTION realtime.subscription_check_filters() TO authenticated;
GRANT ALL ON FUNCTION realtime.subscription_check_filters() TO service_role;
GRANT ALL ON FUNCTION realtime.subscription_check_filters() TO supabase_realtime_admin;


--
-- Name: FUNCTION to_regrole(role_name text); Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON FUNCTION realtime.to_regrole(role_name text) TO postgres;
GRANT ALL ON FUNCTION realtime.to_regrole(role_name text) TO dashboard_user;
GRANT ALL ON FUNCTION realtime.to_regrole(role_name text) TO anon;
GRANT ALL ON FUNCTION realtime.to_regrole(role_name text) TO authenticated;
GRANT ALL ON FUNCTION realtime.to_regrole(role_name text) TO service_role;
GRANT ALL ON FUNCTION realtime.to_regrole(role_name text) TO supabase_realtime_admin;


--
-- Name: FUNCTION topic(); Type: ACL; Schema: realtime; Owner: supabase_realtime_admin
--

GRANT ALL ON FUNCTION realtime.topic() TO postgres;
GRANT ALL ON FUNCTION realtime.topic() TO dashboard_user;


--
-- Name: FUNCTION http_request(); Type: ACL; Schema: supabase_functions; Owner: supabase_functions_admin
--

REVOKE ALL ON FUNCTION supabase_functions.http_request() FROM PUBLIC;
GRANT ALL ON FUNCTION supabase_functions.http_request() TO postgres;
GRANT ALL ON FUNCTION supabase_functions.http_request() TO anon;
GRANT ALL ON FUNCTION supabase_functions.http_request() TO authenticated;
GRANT ALL ON FUNCTION supabase_functions.http_request() TO service_role;


--
-- Name: TABLE audit_log_entries; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT ALL ON TABLE auth.audit_log_entries TO dashboard_user;
GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.audit_log_entries TO postgres;
GRANT SELECT ON TABLE auth.audit_log_entries TO postgres WITH GRANT OPTION;


--
-- Name: TABLE flow_state; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.flow_state TO postgres;
GRANT SELECT ON TABLE auth.flow_state TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE auth.flow_state TO dashboard_user;


--
-- Name: TABLE identities; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.identities TO postgres;
GRANT SELECT ON TABLE auth.identities TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE auth.identities TO dashboard_user;


--
-- Name: TABLE instances; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT ALL ON TABLE auth.instances TO dashboard_user;
GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.instances TO postgres;
GRANT SELECT ON TABLE auth.instances TO postgres WITH GRANT OPTION;


--
-- Name: TABLE mfa_amr_claims; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.mfa_amr_claims TO postgres;
GRANT SELECT ON TABLE auth.mfa_amr_claims TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE auth.mfa_amr_claims TO dashboard_user;


--
-- Name: TABLE mfa_challenges; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.mfa_challenges TO postgres;
GRANT SELECT ON TABLE auth.mfa_challenges TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE auth.mfa_challenges TO dashboard_user;


--
-- Name: TABLE mfa_factors; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.mfa_factors TO postgres;
GRANT SELECT ON TABLE auth.mfa_factors TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE auth.mfa_factors TO dashboard_user;


--
-- Name: TABLE one_time_tokens; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.one_time_tokens TO postgres;
GRANT SELECT ON TABLE auth.one_time_tokens TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE auth.one_time_tokens TO dashboard_user;


--
-- Name: TABLE refresh_tokens; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT ALL ON TABLE auth.refresh_tokens TO dashboard_user;
GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.refresh_tokens TO postgres;
GRANT SELECT ON TABLE auth.refresh_tokens TO postgres WITH GRANT OPTION;


--
-- Name: SEQUENCE refresh_tokens_id_seq; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT ALL ON SEQUENCE auth.refresh_tokens_id_seq TO dashboard_user;
GRANT ALL ON SEQUENCE auth.refresh_tokens_id_seq TO postgres;


--
-- Name: TABLE saml_providers; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.saml_providers TO postgres;
GRANT SELECT ON TABLE auth.saml_providers TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE auth.saml_providers TO dashboard_user;


--
-- Name: TABLE saml_relay_states; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.saml_relay_states TO postgres;
GRANT SELECT ON TABLE auth.saml_relay_states TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE auth.saml_relay_states TO dashboard_user;


--
-- Name: TABLE schema_migrations; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT ALL ON TABLE auth.schema_migrations TO dashboard_user;
GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.schema_migrations TO postgres;
GRANT SELECT ON TABLE auth.schema_migrations TO postgres WITH GRANT OPTION;


--
-- Name: TABLE sessions; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.sessions TO postgres;
GRANT SELECT ON TABLE auth.sessions TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE auth.sessions TO dashboard_user;


--
-- Name: TABLE sso_domains; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.sso_domains TO postgres;
GRANT SELECT ON TABLE auth.sso_domains TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE auth.sso_domains TO dashboard_user;


--
-- Name: TABLE sso_providers; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.sso_providers TO postgres;
GRANT SELECT ON TABLE auth.sso_providers TO postgres WITH GRANT OPTION;
GRANT ALL ON TABLE auth.sso_providers TO dashboard_user;


--
-- Name: TABLE users; Type: ACL; Schema: auth; Owner: supabase_auth_admin
--

GRANT ALL ON TABLE auth.users TO dashboard_user;
GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE auth.users TO postgres;
GRANT SELECT ON TABLE auth.users TO postgres WITH GRANT OPTION;


--
-- Name: TABLE job; Type: ACL; Schema: cron; Owner: supabase_admin
--

GRANT SELECT ON TABLE cron.job TO postgres WITH GRANT OPTION;


--
-- Name: TABLE job_run_details; Type: ACL; Schema: cron; Owner: supabase_admin
--

GRANT ALL ON TABLE cron.job_run_details TO postgres WITH GRANT OPTION;


--
-- Name: TABLE pg_stat_statements; Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON TABLE extensions.pg_stat_statements TO postgres WITH GRANT OPTION;


--
-- Name: TABLE pg_stat_statements_info; Type: ACL; Schema: extensions; Owner: supabase_admin
--

GRANT ALL ON TABLE extensions.pg_stat_statements_info TO postgres WITH GRANT OPTION;


--
-- Name: TABLE decrypted_key; Type: ACL; Schema: pgsodium; Owner: supabase_admin
--

GRANT ALL ON TABLE pgsodium.decrypted_key TO pgsodium_keyholder;


--
-- Name: TABLE masking_rule; Type: ACL; Schema: pgsodium; Owner: supabase_admin
--

GRANT ALL ON TABLE pgsodium.masking_rule TO pgsodium_keyholder;


--
-- Name: TABLE mask_columns; Type: ACL; Schema: pgsodium; Owner: supabase_admin
--

GRANT ALL ON TABLE pgsodium.mask_columns TO pgsodium_keyholder;


--
-- Name: TABLE check_in_logs; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON TABLE public.check_in_logs TO anon;
GRANT ALL ON TABLE public.check_in_logs TO authenticated;
GRANT ALL ON TABLE public.check_in_logs TO service_role;


--
-- Name: TABLE check_ins; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON TABLE public.check_ins TO anon;
GRANT ALL ON TABLE public.check_ins TO authenticated;
GRANT ALL ON TABLE public.check_ins TO service_role;


--
-- Name: TABLE class_schedule; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON TABLE public.class_schedule TO anon;
GRANT ALL ON TABLE public.class_schedule TO authenticated;
GRANT ALL ON TABLE public.class_schedule TO service_role;


--
-- Name: TABLE debug_logs; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON TABLE public.debug_logs TO anon;
GRANT ALL ON TABLE public.debug_logs TO authenticated;
GRANT ALL ON TABLE public.debug_logs TO service_role;


--
-- Name: SEQUENCE debug_logs_id_seq; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON SEQUENCE public.debug_logs_id_seq TO anon;
GRANT ALL ON SEQUENCE public.debug_logs_id_seq TO authenticated;
GRANT ALL ON SEQUENCE public.debug_logs_id_seq TO service_role;


--
-- Name: TABLE members; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON TABLE public.members TO anon;
GRANT ALL ON TABLE public.members TO authenticated;
GRANT ALL ON TABLE public.members TO service_role;


--
-- Name: TABLE membership_cards; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON TABLE public.membership_cards TO anon;
GRANT ALL ON TABLE public.membership_cards TO authenticated;
GRANT ALL ON TABLE public.membership_cards TO service_role;


--
-- Name: TABLE membership_card_view; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON TABLE public.membership_card_view TO anon;
GRANT ALL ON TABLE public.membership_card_view TO authenticated;
GRANT ALL ON TABLE public.membership_card_view TO service_role;


--
-- Name: TABLE migration_logs; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON TABLE public.migration_logs TO anon;
GRANT ALL ON TABLE public.migration_logs TO authenticated;
GRANT ALL ON TABLE public.migration_logs TO service_role;


--
-- Name: SEQUENCE migration_logs_id_seq; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON SEQUENCE public.migration_logs_id_seq TO anon;
GRANT ALL ON SEQUENCE public.migration_logs_id_seq TO authenticated;
GRANT ALL ON SEQUENCE public.migration_logs_id_seq TO service_role;


--
-- Name: TABLE migrations; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON TABLE public.migrations TO anon;
GRANT ALL ON TABLE public.migrations TO authenticated;
GRANT ALL ON TABLE public.migrations TO service_role;


--
-- Name: SEQUENCE migrations_id_seq; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON SEQUENCE public.migrations_id_seq TO anon;
GRANT ALL ON SEQUENCE public.migrations_id_seq TO authenticated;
GRANT ALL ON SEQUENCE public.migrations_id_seq TO service_role;


--
-- Name: TABLE processed_check_ins; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON TABLE public.processed_check_ins TO anon;
GRANT ALL ON TABLE public.processed_check_ins TO authenticated;
GRANT ALL ON TABLE public.processed_check_ins TO service_role;


--
-- Name: TABLE trainers; Type: ACL; Schema: public; Owner: postgres
--

GRANT ALL ON TABLE public.trainers TO anon;
GRANT ALL ON TABLE public.trainers TO authenticated;
GRANT ALL ON TABLE public.trainers TO service_role;


--
-- Name: TABLE messages; Type: ACL; Schema: realtime; Owner: supabase_realtime_admin
--

GRANT ALL ON TABLE realtime.messages TO postgres;
GRANT ALL ON TABLE realtime.messages TO dashboard_user;
GRANT SELECT,INSERT,UPDATE ON TABLE realtime.messages TO anon;
GRANT SELECT,INSERT,UPDATE ON TABLE realtime.messages TO authenticated;
GRANT SELECT,INSERT,UPDATE ON TABLE realtime.messages TO service_role;


--
-- Name: TABLE messages_2025_03_09; Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON TABLE realtime.messages_2025_03_09 TO postgres;
GRANT ALL ON TABLE realtime.messages_2025_03_09 TO dashboard_user;


--
-- Name: TABLE messages_2025_03_10; Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON TABLE realtime.messages_2025_03_10 TO postgres;
GRANT ALL ON TABLE realtime.messages_2025_03_10 TO dashboard_user;


--
-- Name: TABLE messages_2025_03_11; Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON TABLE realtime.messages_2025_03_11 TO postgres;
GRANT ALL ON TABLE realtime.messages_2025_03_11 TO dashboard_user;


--
-- Name: TABLE messages_2025_03_12; Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON TABLE realtime.messages_2025_03_12 TO postgres;
GRANT ALL ON TABLE realtime.messages_2025_03_12 TO dashboard_user;


--
-- Name: TABLE messages_2025_03_13; Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON TABLE realtime.messages_2025_03_13 TO postgres;
GRANT ALL ON TABLE realtime.messages_2025_03_13 TO dashboard_user;


--
-- Name: TABLE messages_2025_03_14; Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON TABLE realtime.messages_2025_03_14 TO postgres;
GRANT ALL ON TABLE realtime.messages_2025_03_14 TO dashboard_user;


--
-- Name: TABLE schema_migrations; Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON TABLE realtime.schema_migrations TO postgres;
GRANT ALL ON TABLE realtime.schema_migrations TO dashboard_user;
GRANT SELECT ON TABLE realtime.schema_migrations TO anon;
GRANT SELECT ON TABLE realtime.schema_migrations TO authenticated;
GRANT SELECT ON TABLE realtime.schema_migrations TO service_role;
GRANT ALL ON TABLE realtime.schema_migrations TO supabase_realtime_admin;


--
-- Name: TABLE subscription; Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON TABLE realtime.subscription TO postgres;
GRANT ALL ON TABLE realtime.subscription TO dashboard_user;
GRANT SELECT ON TABLE realtime.subscription TO anon;
GRANT SELECT ON TABLE realtime.subscription TO authenticated;
GRANT SELECT ON TABLE realtime.subscription TO service_role;
GRANT ALL ON TABLE realtime.subscription TO supabase_realtime_admin;


--
-- Name: SEQUENCE subscription_id_seq; Type: ACL; Schema: realtime; Owner: supabase_admin
--

GRANT ALL ON SEQUENCE realtime.subscription_id_seq TO postgres;
GRANT ALL ON SEQUENCE realtime.subscription_id_seq TO dashboard_user;
GRANT USAGE ON SEQUENCE realtime.subscription_id_seq TO anon;
GRANT USAGE ON SEQUENCE realtime.subscription_id_seq TO authenticated;
GRANT USAGE ON SEQUENCE realtime.subscription_id_seq TO service_role;
GRANT ALL ON SEQUENCE realtime.subscription_id_seq TO supabase_realtime_admin;


--
-- Name: TABLE buckets; Type: ACL; Schema: storage; Owner: supabase_storage_admin
--

GRANT ALL ON TABLE storage.buckets TO anon;
GRANT ALL ON TABLE storage.buckets TO authenticated;
GRANT ALL ON TABLE storage.buckets TO service_role;
GRANT ALL ON TABLE storage.buckets TO postgres;


--
-- Name: TABLE migrations; Type: ACL; Schema: storage; Owner: supabase_storage_admin
--

GRANT ALL ON TABLE storage.migrations TO anon;
GRANT ALL ON TABLE storage.migrations TO authenticated;
GRANT ALL ON TABLE storage.migrations TO service_role;
GRANT ALL ON TABLE storage.migrations TO postgres;


--
-- Name: TABLE objects; Type: ACL; Schema: storage; Owner: supabase_storage_admin
--

GRANT ALL ON TABLE storage.objects TO anon;
GRANT ALL ON TABLE storage.objects TO authenticated;
GRANT ALL ON TABLE storage.objects TO service_role;
GRANT ALL ON TABLE storage.objects TO postgres;


--
-- Name: TABLE s3_multipart_uploads; Type: ACL; Schema: storage; Owner: supabase_storage_admin
--

GRANT ALL ON TABLE storage.s3_multipart_uploads TO service_role;
GRANT SELECT ON TABLE storage.s3_multipart_uploads TO authenticated;
GRANT SELECT ON TABLE storage.s3_multipart_uploads TO anon;


--
-- Name: TABLE s3_multipart_uploads_parts; Type: ACL; Schema: storage; Owner: supabase_storage_admin
--

GRANT ALL ON TABLE storage.s3_multipart_uploads_parts TO service_role;
GRANT SELECT ON TABLE storage.s3_multipart_uploads_parts TO authenticated;
GRANT SELECT ON TABLE storage.s3_multipart_uploads_parts TO anon;


--
-- Name: TABLE hooks; Type: ACL; Schema: supabase_functions; Owner: supabase_functions_admin
--

GRANT ALL ON TABLE supabase_functions.hooks TO postgres;
GRANT ALL ON TABLE supabase_functions.hooks TO anon;
GRANT ALL ON TABLE supabase_functions.hooks TO authenticated;
GRANT ALL ON TABLE supabase_functions.hooks TO service_role;


--
-- Name: SEQUENCE hooks_id_seq; Type: ACL; Schema: supabase_functions; Owner: supabase_functions_admin
--

GRANT ALL ON SEQUENCE supabase_functions.hooks_id_seq TO postgres;
GRANT ALL ON SEQUENCE supabase_functions.hooks_id_seq TO anon;
GRANT ALL ON SEQUENCE supabase_functions.hooks_id_seq TO authenticated;
GRANT ALL ON SEQUENCE supabase_functions.hooks_id_seq TO service_role;


--
-- Name: TABLE migrations; Type: ACL; Schema: supabase_functions; Owner: supabase_functions_admin
--

GRANT ALL ON TABLE supabase_functions.migrations TO postgres;
GRANT ALL ON TABLE supabase_functions.migrations TO anon;
GRANT ALL ON TABLE supabase_functions.migrations TO authenticated;
GRANT ALL ON TABLE supabase_functions.migrations TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: auth; Owner: supabase_auth_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON SEQUENCES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON SEQUENCES  TO dashboard_user;


--
-- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: auth; Owner: supabase_auth_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON FUNCTIONS  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON FUNCTIONS  TO dashboard_user;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: auth; Owner: supabase_auth_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON TABLES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON TABLES  TO dashboard_user;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: cron; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA cron GRANT ALL ON SEQUENCES  TO postgres WITH GRANT OPTION;


--
-- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: cron; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA cron GRANT ALL ON FUNCTIONS  TO postgres WITH GRANT OPTION;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: cron; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA cron GRANT ALL ON TABLES  TO postgres WITH GRANT OPTION;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: extensions; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA extensions GRANT ALL ON SEQUENCES  TO postgres WITH GRANT OPTION;


--
-- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: extensions; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA extensions GRANT ALL ON FUNCTIONS  TO postgres WITH GRANT OPTION;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: extensions; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA extensions GRANT ALL ON TABLES  TO postgres WITH GRANT OPTION;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: graphql; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql GRANT ALL ON SEQUENCES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql GRANT ALL ON SEQUENCES  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql GRANT ALL ON SEQUENCES  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql GRANT ALL ON SEQUENCES  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: graphql; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql GRANT ALL ON FUNCTIONS  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql GRANT ALL ON FUNCTIONS  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql GRANT ALL ON FUNCTIONS  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql GRANT ALL ON FUNCTIONS  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: graphql; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql GRANT ALL ON TABLES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql GRANT ALL ON TABLES  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql GRANT ALL ON TABLES  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql GRANT ALL ON TABLES  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: graphql_public; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON SEQUENCES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON SEQUENCES  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON SEQUENCES  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON SEQUENCES  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: graphql_public; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON FUNCTIONS  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON FUNCTIONS  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON FUNCTIONS  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON FUNCTIONS  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: graphql_public; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON TABLES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON TABLES  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON TABLES  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON TABLES  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: pgsodium; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA pgsodium GRANT ALL ON SEQUENCES  TO pgsodium_keyholder;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: pgsodium; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA pgsodium GRANT ALL ON TABLES  TO pgsodium_keyholder;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: pgsodium_masks; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA pgsodium_masks GRANT ALL ON SEQUENCES  TO pgsodium_keyiduser;


--
-- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: pgsodium_masks; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA pgsodium_masks GRANT ALL ON FUNCTIONS  TO pgsodium_keyiduser;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: pgsodium_masks; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA pgsodium_masks GRANT ALL ON TABLES  TO pgsodium_keyiduser;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: public; Owner: postgres
--

ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: public; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: public; Owner: postgres
--

ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: public; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: public; Owner: postgres
--

ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: public; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: realtime; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON SEQUENCES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON SEQUENCES  TO dashboard_user;


--
-- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: realtime; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON FUNCTIONS  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON FUNCTIONS  TO dashboard_user;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: realtime; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON TABLES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON TABLES  TO dashboard_user;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: storage; Owner: postgres
--

ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON SEQUENCES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON SEQUENCES  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON SEQUENCES  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON SEQUENCES  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: storage; Owner: postgres
--

ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON FUNCTIONS  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON FUNCTIONS  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON FUNCTIONS  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON FUNCTIONS  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: storage; Owner: postgres
--

ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON TABLES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON TABLES  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON TABLES  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON TABLES  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: supabase_functions; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA supabase_functions GRANT ALL ON SEQUENCES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA supabase_functions GRANT ALL ON SEQUENCES  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA supabase_functions GRANT ALL ON SEQUENCES  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA supabase_functions GRANT ALL ON SEQUENCES  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: supabase_functions; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA supabase_functions GRANT ALL ON FUNCTIONS  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA supabase_functions GRANT ALL ON FUNCTIONS  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA supabase_functions GRANT ALL ON FUNCTIONS  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA supabase_functions GRANT ALL ON FUNCTIONS  TO service_role;


--
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: supabase_functions; Owner: supabase_admin
--

ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA supabase_functions GRANT ALL ON TABLES  TO postgres;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA supabase_functions GRANT ALL ON TABLES  TO anon;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA supabase_functions GRANT ALL ON TABLES  TO authenticated;
ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA supabase_functions GRANT ALL ON TABLES  TO service_role;


--
-- Name: issue_graphql_placeholder; Type: EVENT TRIGGER; Schema: -; Owner: supabase_admin
--

CREATE EVENT TRIGGER issue_graphql_placeholder ON sql_drop
         WHEN TAG IN ('DROP EXTENSION')
   EXECUTE FUNCTION extensions.set_graphql_placeholder();


ALTER EVENT TRIGGER issue_graphql_placeholder OWNER TO supabase_admin;

--
-- Name: issue_pg_cron_access; Type: EVENT TRIGGER; Schema: -; Owner: supabase_admin
--

CREATE EVENT TRIGGER issue_pg_cron_access ON ddl_command_end
         WHEN TAG IN ('CREATE EXTENSION')
   EXECUTE FUNCTION extensions.grant_pg_cron_access();


ALTER EVENT TRIGGER issue_pg_cron_access OWNER TO supabase_admin;

--
-- Name: issue_pg_graphql_access; Type: EVENT TRIGGER; Schema: -; Owner: supabase_admin
--

CREATE EVENT TRIGGER issue_pg_graphql_access ON ddl_command_end
         WHEN TAG IN ('CREATE FUNCTION')
   EXECUTE FUNCTION extensions.grant_pg_graphql_access();


ALTER EVENT TRIGGER issue_pg_graphql_access OWNER TO supabase_admin;

--
-- Name: issue_pg_net_access; Type: EVENT TRIGGER; Schema: -; Owner: postgres
--

CREATE EVENT TRIGGER issue_pg_net_access ON ddl_command_end
         WHEN TAG IN ('CREATE EXTENSION')
   EXECUTE FUNCTION extensions.grant_pg_net_access();


ALTER EVENT TRIGGER issue_pg_net_access OWNER TO postgres;

--
-- Name: pgrst_ddl_watch; Type: EVENT TRIGGER; Schema: -; Owner: supabase_admin
--

CREATE EVENT TRIGGER pgrst_ddl_watch ON ddl_command_end
   EXECUTE FUNCTION extensions.pgrst_ddl_watch();


ALTER EVENT TRIGGER pgrst_ddl_watch OWNER TO supabase_admin;

--
-- Name: pgrst_drop_watch; Type: EVENT TRIGGER; Schema: -; Owner: supabase_admin
--

CREATE EVENT TRIGGER pgrst_drop_watch ON sql_drop
   EXECUTE FUNCTION extensions.pgrst_drop_watch();


ALTER EVENT TRIGGER pgrst_drop_watch OWNER TO supabase_admin;

--
-- PostgreSQL database dump complete
--

